Etoya
Etoya

Reputation: 239

Limit nested Array Recursively JavaScript

let's say i have a data :

const myArr = [
    {   
      id: '123',
      items: [{   
      id: '123',
      items: []
     },
     {   
      id: '123',
      items: []
     },
     {   
      id: '123',
      items: []
     }]
     },
     {   
      id: '123',
      items: []
     },
     {   
      id: '123',
      items: []
     }
    
]

I want to slice items recursively. Let's say if I want to only return a count of 2, it should filter the first 'items' to just 2 record and the nested items as well to 2 records.

so far I have this code and I am already very confused

const applyLimitRecursive = (arr) => {
  var result
  for (let i = 0; i < arr.length; i++) {
    if (!arr[i].items) {
      result = arr[i]
      break
    } else {
      result = applyLimitRecursive(arr[i].items)
      if (result) break
    }
  }
  return result
}

Upvotes: 1

Views: 103

Answers (2)

StackSlave
StackSlave

Reputation: 10617

I'm not exactly sure what you're looking for, but I'm guessing this is it?

function deeper(array, deep){
  if(array.length-1 < deep){
    return undefined;
  }
  const q = array[deep];
  if(typeof q === 'object' && q.items instanceof Array){
    return deeper(q.items, deep);
  }
  return q;
}
const myArr = [
  { // 0   
    id: '123a',
      items: [
        {   
          id: '123',
          items: ['zero', 'one', 2]
        },
      {   
        id: '123',
        items: []
      },
      {   
        id: '123',
        items: ['a']
     }]
   },
   { // 1 
     id: '123',
     items: [
       {
         id: '456',
         items : [
           {
             more: 'stuff',
             lame: false,
             id: '25',
             items: ['c', 'd']
           }
         ]
       },
       {
         id: '456',
         items : [
           {
             items: ['a', 'b']
           },
           {
             more: 'yup',
             lame: true,
             id: 789,
             items: ['see', 'one', 'test']
           }
         ]
       }
     ]
   },
   { // 2
     id: '123',
     items: []
   } 
]
console.log(deeper(myArr, 0));
console.log(deeper(myArr, 1));
console.log(deeper(myArr, 2));

Note that deep is index based.

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 371049

If the data is serializable, you could use JSON.parse's revival function. If the value being iterated over is an array, return a .slice(0, 2) from it:

const result = JSON.parse(
  JSON.stringify(myArr),
  (_, val) => Array.isArray(val) ? val.slice(0, 2) : val
);

const myArr = [
  {   
    id: '123',
    items: [
      {
        id: 234,
        items: [
          { id: 5 },
          { id: 6 },
          { id: 7 },
        ]
      },
    ]
  }
];
const result = JSON.parse(
  JSON.stringify(myArr),
  (_, val) => Array.isArray(val) ? val.slice(0, 2) : val
);
console.log(result);

Or, to do it more manually:

const transform = (item) => {
  if (Array.isArray(item)) {
    return item.map(transform).slice(0, 2);
  }
  if (typeof item === 'object' && item !== null) {
    return Object.fromEntries(
      Object.entries(item).map(
        ([key, val]) => [key, transform(val)]
      )
    );
  }
  // primitives:
  return item;
};
const result = transform(myArr);

const myArr = [
  {   
    id: '123',
    items: [
      {
        id: 234,
        items: [
          { id: 5 },
          { id: 6 },
          { id: 7 },
        ]
      },
    ]
  }
];
const transform = (item) => {
  if (Array.isArray(item)) {
    return item.map(transform).slice(0, 2);
  }
  if (typeof item === 'object' && item !== null) {
    return Object.fromEntries(
      Object.entries(item).map(
        ([key, val]) => [key, transform(val)]
      )
    );
  }
  // primitives:
  return item;
};
const result = transform(myArr);
console.log(result);

Upvotes: 2

Related Questions