2

Getting data from graphql, example:

const data = [
  {
    items: [
      {
        link: '/monday',
        name: 'Monday',
      },
      {
        link: '/tuesday',
        name: 'Tuesday',
      },
      {
        link: '/wednesday',
        name: 'Wednesday',
      },
    ],
  },
  {
    items: [
      {
        link: '/january',
        name: 'January',
      },
      {
        link: '/february',
        name: 'February',
      },
      {
        link: '/march',
        name: 'March',
      },
    ],
  },
]

I'm trying to build a new object and also add a unique id but it takes me two loops to accomplish (also includes expected output):

  const data = [
    {
      items: [
        {
          link: '/monday',
          name: 'Monday',
        },
        {
          link: '/tuesday',
          name: 'Tuesday',
        },
        {
          link: '/wednesday',
          name: 'Wednesday',
        },
      ],
    },
    {
      items: [
        {
          link: '/january',
          name: 'January',
        },
        {
          link: '/february',
          name: 'February',
        },
        {
          link: '/march',
          name: 'March',
        },
      ],
    },
  ]
  
  let itemsObj = []
  let merge = []

  data.forEach(section => {
    section.items.forEach((item, i) => {
      return (itemsObj = [...itemsObj, item])
    })
  })

  itemsObj.map((item, i) => {
    item.id = i
    return merge.push(item)
  })
  
  console.log(itemsObj)

Code that correctly builds what I need but takes a foreach and map:

data.forEach(section => {
  section.items.forEach((item, i) => {
    return (itemsObj = [...itemsObj, item])
  })
})

itemsObj.map((item, i) => {
  item.id = i
  return merge.push(item)
})

When I try to add an incremented id in one loop it starts over, example:

const data = [
  {
    items: [
      {
        link: '/monday',
        name: 'Monday',
      },
      {
        link: '/tuesday',
        name: 'Tuesday',
      },
      {
        link: '/wednesday',
        name: 'Wednesday',
      },
    ],
  },
  {
    items: [
      {
        link: '/january',
        name: 'January',
      },
      {
        link: '/february',
        name: 'February',
      },
      {
        link: '/march',
        name: 'March',
      },
    ],
  },
]

 let itemsObj = []

  data.forEach(section => {
    section.items.forEach((item, i) => {
      item.id = i
      return (itemsObj = [...itemsObj, item])
    })
  })
  
  console.log(itemsObj)

Code trying to add the id and build the object in one loop that causes the id to start over:

let itemsObj = []

data.forEach(section => {
  section.items.forEach((item, i) => {
    item.id = i
    return (itemsObj = [...itemsObj, item])
  })
})

console.log(itemsObj)

Per answer same issue occurs with an id that isn't unique:

data.flatMap(dataObj => {
  return dataObj.items.map((item, i) => {
    return { i, ...item }
  })
})

Expected output example to clarify comment:

[
  {
    "link": "/monday",
    "name": "Monday",
    "id": 0
  },
  {
    "link": "/tuesday",
    "name": "Tuesday",
    "id": 1
  },
  {
    "link": "/wednesday",
    "name": "Wednesday",
    "id": 2
  },
  {
    "link": "/january",
    "name": "January",
    "id": 3
  },
  {
    "link": "/february",
    "name": "February",
    "id": 4
  },
  {
    "link": "/march",
    "name": "March",
    "id": 5
  }
]

Research:

Is there a way to an id in one loop instead of using a foreach and map?

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127

3 Answers3

3

You can create a variable outside of flatMap and increment after it gets added to end result.

You can even make it a one-liner if you'd like

const result = data.flatMap(({ items }) =>  items.map((item) => ({ i: start++, ...item })));

1) With flatMap

const data = [
  {
    items: [
      {
        link: "/monday",
        name: "Monday",
      },
      {
        link: "/tuesday",
        name: "Tuesday",
      },
      {
        link: "/wednesday",
        name: "Wednesday",
      },
    ],
  },
  {
    items: [
      {
        link: "/january",
        name: "January",
      },
      {
        link: "/february",
        name: "February",
      },
      {
        link: "/march",
        name: "March",
      },
    ],
  },
];

let start = 0;
const result = data.flatMap(({ items }) => {
  return items.map((item) => {
    return { i: start++, ...item };
  });
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2) With reduce

const data = [
  {
    items: [
      {
        link: "/monday",
        name: "Monday",
      },
      {
        link: "/tuesday",
        name: "Tuesday",
      },
      {
        link: "/wednesday",
        name: "Wednesday",
      },
    ],
  },
  {
    items: [
      {
        link: "/january",
        name: "January",
      },
      {
        link: "/february",
        name: "February",
      },
      {
        link: "/march",
        name: "March",
      },
    ],
  },
];

const result = data.reduce((acc, { items }, index) => {
  return [
    ...acc,
    ...items.map((o, i) => ({ i: acc.length * index + i, ...o })),
  ];
}, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
DecPK
  • 24,537
  • 6
  • 26
  • 42
1

Try flatMap

let index = 0
data.flatMap(dataObj => {
  return dataObj.items.map((item) => {
    return { i: index++, ...item }
  })
})
DecPK
  • 24,537
  • 6
  • 26
  • 42
0
let itemsObj = []
let index = 0;

data.forEach(section => {
  section.items.forEach((item) => {
    item.id = index;
    index++;
    return (itemsObj = [...itemsObj, item])
  })
})

console.log(itemsObj)
Aayush Mall
  • 963
  • 8
  • 20