1

I have an array of arrays, which contain objects, would like to get the value of a certain key and return it as a big array, have tried a nested map but it returns multiple array's rather than a single array.

const items = [
  {
    id: 1,
    sub_items: [
      {
        id: 1
      },
      {
        id: 2
      },
      {
        id: 3
      }
    ]
  },
  {
    id: 2,
    sub_items: [
      {
        id: 4
      },
      {
        id: 5
      },
      {
        id: 6
      }
    ]
  }
]

const subItemIDs = items.map( (item) =>
  item.sub_items.map( (subItem) => subItem.id )
)

console.log(subItemIDs);

Expected output

[1, 2, 3, 4, 5, 6]

Actual output

[ [1,2,3], [4,5,6] ]
1
  • 1
    what should be the output looks like? Commented May 27, 2021 at 20:13

5 Answers 5

2

You can use arrays.flat(). I can provide more specific code once output is mentioned in the question

const arr1 = [0, 1, 2, [3, 4]];

console.log(arr1.flat());
// expected output: [0, 1, 2, 3, 4]

const arr2 = [0, 1, 2, [[[3, 4]]]];

console.log(arr2.flat(2));
// expected output: [0, 1, 2, [3, 4]]
Sign up to request clarification or add additional context in comments.

Comments

1

You could take Array#flatMap to get a flat array from nested arrays.

const
    items = [{ id: 1, sub_items: [{ id: 1 }, { id: 2 }, { id: 3 }] }, { id: 2, sub_items: [{ id: 4 }, { id: 5 }, { id: 6 }] }],
    subItemIDs = items.flatMap(({ sub_items }) => sub_items.map(({ id }) => id));

console.log(subItemIDs);

Comments

1

Achieved this with:

const items = [
  {
    id: 1,
    sub_items: [
      {
        id: 1
      },
      {
        id: 2
      },
      {
        id: 3
      }
    ]
  },
  {
    id: 2,
    sub_items: [
      {
        id: 4
      },
      {
        id: 5
      },
      {
        id: 6
      }
    ]
  }
]

const subItemIDs = [].concat(...items.map( (item) =>
  item.sub_items.map( (subItem) => subItem.id )
))

console.log(subItemIDs);

Comments

0

Sometimes, the obvious is the easiest: Given a data structure that looks like this

const items = [
  { id: 1, sub_items: [ { id: 1 }, { id: 2 }, { id: 3 }, ] },
  { id: 2, sub_items: [ { id: 4 }, { id: 5 }, { id: 6 }, ] },
];

A trivial function like this

function extract_item_ids( items ) {
  const ids = [];
  for ( const item of items ) {
    for ( const {id} of sub_items ) {
      ids.push(id);
    }
  }
  return ids;
}

should do the trick. If you want to collect the ids from a tree of any depth, it's just as easy:

function extract_item_ids( items ) {
  const ids = [];

  const pending = items;
  while ( pending.length > 0 ) {
    const item = pending.pop();

    ids.push(item.id);
    pending.push(...( item.sub_items || [] ) );

  }

  return ids;
}

And collecting the set of discrete item IDs is no more difficult: If you want to collect the ids from a tree of any depth, it's just as easy:

function extract_item_ids( items ) {
  const ids = new Set();

  const pending = [...items];
  while ( pending.length > 0 ) {
    const item = pending.pop();

    ids.add(item.id);
    pending.push(...( item.sub_items || [] ) );

  }

  return Array.from(ids);
}

Comments

0

As is the case with most things JavaScript, you have several options. Some are more efficient than others, others have a certain stylistic purity, others might better speak to your fancy. Here are a few:

Array.flat

With array flat you can take your original code and have the JS Engine flatten the array down to a one-dimensional array. Simply append .flat() onto the end of your map.

const items = [
  { id: 1, sub_items: [ { id: 1 }, { id: 2 }, { id: 3 }, ] },
  { id: 2, sub_items: [ { id: 4 }, { id: 5 }, { id: 6 }, ] },
];

const subItemIds = items.map( (item) =>
  item.sub_items.map( (subItem) => subItem.id )
).flat()

console.log(subItemIds);

Array.reduce

Another method is to use reduce to iterate over the object and build an accumulation array using Array.reduce. In the example below, when pushing onto the array, the spread operator (...) is used to break the array into elements.

const items = [
  { id: 1, sub_items: [ { id: 1 }, { id: 2 }, { id: 3 }, ] },
  { id: 2, sub_items: [ { id: 4 }, { id: 5 }, { id: 6 }, ] },
];

const subItemIds = items.reduce((arr,item) => (
   arr.push(...item.sub_items.map((subItem) => subItem.id)), arr
),[])

console.log(subItemIds);

Other

Other answers here make use of custom functions or Array.flatMap, which should be explored as they could lead to more readable and efficient code, depending on the program's needs.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.