0

I have this JSON array tree that can include any number of nested arrays:

const namesArrayTree = [
    {
        "name": "Peter"
    },
    {
        "name": "folder1",
        "isArray": true,
        "namesArray": [
            {
                "name": "Paul"
            },
            {
                "name": "folder2",
                "isArray": true,
                "namesArray": [
                    {
                        "name": "Mary"
                    },
                    {
                        "name": "John"
                    }
                ]
            }
        ]
    },
    {
        "name": "Mark"
    }
]

I need to transform it to a flat array including only the names:

const namesArrayFlat = [ "Peter", "Paul", "Mary", "John", "Mark" ]

So I'm using this code to do the transformation:

const namesArrayTree = [
    {
        "name": "Peter"
    },
    {
        "name": "folder1",
        "isArray": true,
        "namesArray": [
            {
                "name": "Paul"
            },
            {
                "name": "folder2",
                "isArray": true,
                "namesArray": [
                    {
                        "name": "Mary"
                    },
                    {
                        "name": "John"
                    }
                ]
            }
        ]
    },
    {
        "name": "Mark"
    }
] ;

  function getNamesList(item) {
    let name = item.name;
    let isArray = item.isArray;

    if (isArray) {
      name = item.namesArray.map(getNamesList).join("\r\n");
    }
    return name;
  }

  const namesList = namesArrayTree.map(getNamesList).join("\r\n");
  const namesArrayFlat = namesList.split("\r\n");
  
  console.log(namesArrayFlat)

The code works well, but I would like to get rid of the extra steps to create a list with the names using join.("\r\n") and then convert to array using split("\r\n").

That is, I would like to reduce the code by removing the following:

     function getNamesList(item) {
        let name = item.name;
        let isArray = item.isArray;

        if (isArray) {
/* remove code to join by "\r\n" */
          name = item.namesArray.map(getNamesList) 
        }
        return name;
      }
/* remove code to create "namesList" constant and remove code to join by "\r\n") */
      const namesArrayFlat = namesArrayTree.map(getNamesList) 
      
      console.log(namesArrayFlat)

(The above code still returns a tree nested arrays structure)

Any ideas about how to get rid of the extra code? also any suggestions about how to improve the code would be great, thanks!

1
  • Suggested way of flatten json here as answer to similar question. Commented May 11, 2022 at 9:31

2 Answers 2

1
function getNamesList(item) {
    return item.isArray ? item.namesArray.map(getNamesList) : item.name
}

const names = namesArrayTree.map(getNamesList).flat(Infinity)

console.log(names)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, very elegant. I didn't know about "flat" and "Infinity".
Indeed, there is also flatMap, but that only allows for depth == 1, and in your case you need more depth.
1

You can achieve this with an array reducer as follows:

const namesArray = [
  {
    "name": "Peter"
  },
  {
    "name": "folder1",
    "isArray": true,
    "namesArray": [
      {
        "name": "Paul"
      },
      {
        "name": "folder2",
        "isArray": true,
        "namesArray": [
          {
            "name": "Mary"
          },
          {
            "name": "John"
          }
        ]
      }
    ]
  },
  {
    "name": "Mark"
  }
] ;

function reduceNamesList(list, item) {
  if (item.isArray) {
    return item.namesArray.reduce(reduceNamesList, list);
  }

  list.push(item.name)

  return list
}

const namesList = namesArray.reduce(reduceNamesList, [])
console.log(namesList)

4 Comments

I should add, the mechanism of using flat is perfectly suitable and in a way simpler, but understanding reducers is going to do you very well for other problems you'll encounter in future involving traversing nested structures.
Thank you, that's a correct solution, but the other answer has less code.
Thank you for the tip about using reduce, I should had tried that to start with.
Yes that's reasonable; in JS the other answer is simpler. One thing worth bearing in mind is that this concept/requirement is by no means limited to JS, and the specific use of flat is less likely to transpose into other languages. Conversely, most higher level languages will have map and reduce methods for list-like objects.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.