2

I have an array of objects with this structure:

const treeData = [
  { 0: ["0-0", "0-1"] },
  { 1: ["1-0", "1-1"] }
]

It could be deeper but array data would be always json or strings

const treeData = [
  { 0: ["0-0", "0-1"] },
  { 1: ["1-0", "1-1"] },
    2,
    3
]

I would like to get something like this:

const treeDataResult = [
  {
    label: "0",
    value: "0",
    children: [
      {
        label: "0-0",
        value: "0-0"
      },
      {
        label: "0-1",
        value: "0-1",
      }
    ]
  },
  {
    label: "1",
    value: "1",
    children: [
      {
        label: "1-0",
        value: "1-0",
      },
      {
        label: "1-1",
        value: "1-1",
      }
    ]
  },
  { 
    label: "2",
    value: "2"
  },
  { 
    label: "3",
    value: "3"
  }
]

My code right now is this:

const treeData = [
      { "0": ["0-0", "0-1"] },
      { "1" : ["1-0", "1-1"] }
    ];

const convertNode = (parentNode) =>
  parentNode.map(
    childnode => {
      if (typeof(childNode) === 'string')
        return {
          label: childNode,
          value: childNode
        }
      else
        return
      childNode.map((key, val) =>
        ({
          label: key,
          value: key,
          children: convertNode(val)
        })
      )
    }
  )

var treeDataResult = convertNode(treeData);
console.log(treeDataResult);
str
  • 42,689
  • 17
  • 109
  • 127
user2670996
  • 2,654
  • 6
  • 29
  • 45
  • What does not work in your current code? – Bergi May 28 '18 at 21:58
  • 1
    The `typeof` of `2` and `3` would be `"number"`, not `"string"`. Also if your node is an object, it might not be an array - you need to actually get that single key you're (ab)using as a label. – Bergi May 28 '18 at 21:58
  • You cannot have an enter after return. If you want it on a new line then do: `return ( (new line here ok)childNode.map... )` – HMR May 28 '18 at 22:14
  • You mistake JavaScript objects for JSON. They are not the same. JSON is *always* a string. – Mulan May 29 '18 at 03:29
  • Objects like `{ 0 : "foo" }` and `{ 1: "bar" }` are bad when the key is a variable. In order for your program to extract the key's value, `Object.keys` or `Object.entries` must be used. Compared to something like `{ key: 0, value: "foo" }` where `key` and `value` are known – extracting each value is just a matter of reading their respective properties. – Mulan May 29 '18 at 03:39
  • Please read [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – str May 29 '18 at 07:44

4 Answers4

1

If the shape of your data is correct I've used reduce and map to get the data into the correct shape and the rest operator so that the objects are in one array

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

const treeData = [
  {
    0: ["0-0", "0-1"]
  },
  {
    1: ["1-0", "1-1"]
  },
  {
    2: null
  },
  {
    3: []
  },
  {
    4: ["0-1"]
  }
]

const changeShape = data => {
  return data.reduce((prev, curr) => [...prev, ...shape(curr)], []);
}

const shape = item => Object.keys(item).map(key => data(item, key));

const data = (item, key) => {
  return !item[key] || !item[key].length > 0 ?
    labelValue(key) : 
    {
      ...labelValue(key),
      children: item[key].map(i => labelValue(i))
    }
}

const labelValue = v => {
  return {
    label: v,
    value: v
  }
}

console.log(changeShape(treeData))
Joe Warner
  • 3,335
  • 1
  • 14
  • 41
1

If JSON.parse is used to get the data, you can try something like this:

var j = '[ { "0": ["0-0", "0-1"] }, { "1": ["1-0", "1-1"] }, 2, 3 ]'

var o = JSON.parse(j, (k, v) => (k = v.constructor) === Array ? v : 
  k !== Object ? ({ label: v, value: v }) :
  ({ label: k = Object.keys(v)[0], value: k,  children: v[k] }) )

console.log( o )
Slai
  • 22,144
  • 5
  • 45
  • 53
0

a primitive solution

    const treeData = [
          { 0 : ["0-0", "0-1"] },
          { 1 : ["1-0", "1-1"] }
        ]
        
        let treeDataResult = [];
        
        
        for(i = 0; i < treeData.length; i++) {
          let current = treeData[i],
          label = Object.getOwnPropertyNames(current),
        
          obj = {
            label: label,
            value: label,
            children: []
          }
          
         for(j = 0; j < current[i].length; j++) {
            let childData = current[i][j],
            child = {
            label : childData,
            value : childData
          } 
          obj.children.push(child)  
         }
        treeDataResult.push(obj)
        }

       console.log(JSON.stringify(treeDataResult, null, 4));
Anders Pedersen
  • 2,255
  • 4
  • 25
  • 49
0
const treeData = [
  { "0": ["0-0", "0-1"] },
  { "1" : ["1-0", "1-1"] }
];

const convertNode = (parentNode) => {
  console.log(parentNode)
  return parentNode.map(
    childNode => {
      if (typeof childNode === 'string')
        return {
          label: childNode,
          value: childNode
        }
      else
        return {
          label: Object.entries(childNode)[0][0],
          value: Object.entries(childNode)[0][0],
          children: convertNode(Object.entries(childNode)[0][1])
        }
    }
  )
}
user2670996
  • 2,654
  • 6
  • 29
  • 45