skip to Main Content
let list=[{key1,children[]},{key2,children[]},{key3,children[]}]

How to get an array like this with javascript?

list1=[{key1,children[{key2,children[{key3,children[]}]}]}

I tried like this

for (let i = 0; i < list.length; i++) {
  if (list[i + 1]) {
    list[0].children.push(list[i + 1]);
  }
}

but its pushing all children into list[0].children

3

Answers


  1. You’ll need to process your original list in reverse order, something like this should do it:

    let list=[{"key":"key1", "children":[]},{"key":"key2", "children":[]},{"key":"key3", "children":[]}]
    
    let result = list.reverse().reduce( (acc,x,i, e) => {
       if(i == list.length-1){
          acc.push(x);
       }
       else{
          e[i+1].children = [x]
       }
       return acc;
       
    },[]);
    
    
    console.log(result);
    Login or Signup to reply.
  2. Here is an alternative solution to Jamiec answer.

    When the data is transformed, it does not mutate list, since a structuredClone is created. I also reduced right-to-left, because when the index reaches 0, we will just return [item]. We do need to set a non-undefined value for the reducer initialized value. The value null will work.

    While the index is greater than 0, push the item as a child to the left of it.

    const list = [
      { key: "key1", children: [] },
      { key: "key2", children: [] },
      { key: "key3", children: [] }
    ]
    
    const transformed = structuredClone(list)
      .reduceRight((acc, item, index, ref) => {
        if (index === 0) return [item];
        ref[index - 1].children.push(item);
      }, null);
    
    console.log(transformed);
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    @Jamiec, instead of reversing the list, you can change the indexing. Be careful, this still modifies the original list array!

    const list = [
      { key: "key1", children: [] },
      { key: "key2", children: [] },
      { key: "key3", children: [] }
    ]
    
    let result = list.reduce((acc, x, i, e) => {
      if (i === 0) {
        acc.push(x);
      } else {
        e[i - 1].children = [x]
      }
      return acc;
    }, []);
    
    console.log(result);
    .as-console-wrapper { top: 0; max-height: 100% !important; }
    Login or Signup to reply.
  3. Avoid structuredClone() at all costs since it’s a slow way to clone objects unless you want object references preserved. Use JSON.parse(JSON.stringify(object)) rather on data acting as data, not as a functional object.
    For your case if you want a copy of the data, just create your custom clone() function:

    const list = [
      { key: "key1", children: [] },
      { key: "key2", children: [] },
      { key: "key3", children: [] }
    ]
    
    const clone = elem => ({key:elem.key, children:[...elem.children]});
    
    const result = [];
    let head = result[0] = clone(list[0]);
    for(let i = 1; i < list.length; i++){
      head.children.push(head = clone(list[i]));
    }
    console.log(result);
    .as-console-wrapper { top: 0; max-height: 100% !important; }

    And a benchmark against structuredClone(): 33x faster:

    Cycles: 600000 / Chrome/117
    ---------------------------------------------------------
    Alexander     38/min   1.0x    40    40    38    41    45
    Polywhirl   1251/min  32.9x  1308  1272  1289  1251  1266
    ---------------------------------------------------------
    https://github.com/silentmantra/benchmark
    
    <script benchmark="600000">
    
    const list = [
      { key: "key1", children: [] },
      { key: "key2", children: [] },
      { key: "key3", children: [] }
    ]
    
    // @benchmark Polywhirl
    
    structuredClone(list)
      .reduceRight((acc, item, index, ref) => {
        if (index === 0) return [item];
        ref[index - 1].children.push(item);
      }, null);
    
    
    // @benchmark Alexander
    
    const clone = elem => ({key:elem.key, children:[...elem.children]});
    
    const result = [];
    let head = result[0] = clone(list[0]);
    for(let i = 1; i < list.length; i++){
      head.children.push(head = clone(list[i]));
    }
    result;
    </script>
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search