【问题标题】:How to add a unique id to an array in one loop instead of two?如何在一个循环而不是两个循环中向数组添加唯一 ID?
【发布时间】:2021-06-06 15:37:57
【问题描述】:

从graphql获取数据,例子:

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',
      },
    ],
  },
]

我正在尝试构建一个新对象并添加一个唯一的id,但我需要两个循环才能完成(还包括预期的输出):

  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)

正确构建我需要但需要 foreachmap 的代码:

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

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

当我尝试在一个循环中添加递增的id 时,它会重新开始,例如:

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)

代码尝试添加 id 并在一个循环中构建对象,导致 id 重新开始:

let itemsObj = []

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

console.log(itemsObj)

根据answer 相同的问题出现在不唯一的id 上:

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

预期的输出示例以澄清评论:

[
  {
    "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
  }
]

研究:

有没有办法在一个循环中使用id 而不是使用foreachmap

【问题讨论】:

  • 你的预期输出是什么?
  • @decpk 上面运行的例子有一个foreachmap 循环?
  • 一个循环是什么意思,因为在第二个代码块中您仍在使用嵌套循环。
  • 使用代码 sn-ps 编辑的问题。

标签: javascript node.js


【解决方案1】:

您可以在flatMap 之外创建一个变量,并在添加到最终结果后递增。

如果你愿意,你甚至可以把它做成单线

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

1) 使用平面地图

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) 减少

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; }

【讨论】:

  • 感谢从未使用过flatmap,所以学到了一些新东西。
  • 对于应该使用的性能,reduceflatmap?
  • 性能没有太大区别,任何人都可以使用。刚想到就分享出来,这样可以帮助你更好的理解...
  • 这是你应该从我的回答中拿走的独特价值,即i: acc.length * index + i
  • @DᴀʀᴛʜVᴀᴅᴇʀ - 注意 OP。这仍然是多个循环 - 它现在稍微隐藏了一点。没有多个循环,没有办法迭代一个对象数组,每个对象都有自己的数组。
【解决方案2】:

试试flatMap

let index = 0
data.flatMap(dataObj => {
  return dataObj.items.map((item) => {
    return { i: index++, ...item }
  })
})

【讨论】:

    【解决方案3】:
    let itemsObj = []
    let index = 0;
    
    data.forEach(section => {
      section.items.forEach((item) => {
        item.id = index;
        index++;
        return (itemsObj = [...itemsObj, item])
      })
    })
    
    console.log(itemsObj)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      相关资源
      最近更新 更多