如何对嵌套数组进行分组和排序并根据第一次出现保持原始顺序?

How to group and sort a nested array and keep the original order based on the first occurrence?

我有一个平面数组,并且已经正确排序。要在 UI 中显示它,我需要按 placeId 对它进行排序,保持 placeId 顺序以及 data 中元素的顺序 属性.

const sortedData = [
  { id: 1, placeId: 12 },
  { id: 5, placeId: 12 },
  { id: 8, placeId: 31 },
  { id: 16, placeId: 31 },
  { id: 20, placeId: 45 },
  { id: 22, placeId: 45 },
]
// maintain order of place as well as data based on first appearance in sortedData
const uiPreparedData = [
  {
    place: 12,
    data: [
      { id: 1, placeId: 12 },
      { id: 5, placeId: 12 },
    ],
  },

  {
    place: 31,
    data: [
      { id: 8, placeId: 31 },
      { id: 16, placeId: 31 },
    ],
  },
  {
    place: 45,
    data: [
      { id: 20, placeId: 45 },
      { id: 22, placeId: 45 },
    ],
  },
]

基于我找到了以下包含lodash的解决方案。但是,我无法将它应用于我的案例的嵌套结构。


  var uiPreparedData = _.chain(sortedData)
    // Group the elements of Array based on `place` property
    .groupBy("placeId")
    .sortBy((item) => item.indexOf(item[0]))
    // `key` is group's name (place), `value` is the array of objects
    .map((value, key) => ({ place: key, data: value }))
    .value();

由于您的 sortedArray 已经正确排序,看来 运行 您在 lodash 链中没有 .sortBy 的代码已经给了您预期的结果。

但是,如果我对问题的理解正确,您希望保持基于 placeId 的 groupBy 顺序,因为它在 sortedArray 中的顺序(按 id 顺序) ), 正确的?如果是这样,请对您的代码进行更正:

  1. 传递给 .sortBy 参数的函数应该是 item => sortedData.indexOf(item[0])
  2. 由于 placeId 对于 data 数组中的每个项目都是相同的,因此 place 属性 可以等于第一个 placeId 值排序数组:place: value[0].placeId

这是一个例子:

const sortedData = [
  { id: 1, placeId: 12 },
  { id: 5, placeId: 12 },
  { id: 6, placeId: 45 }, // Added to demonstrate order
  { id: 8, placeId: 31 },
  { id: 16, placeId: 31 },
  { id: 20, placeId: 45 },
  { id: 22, placeId: 45 },
]

const uiPreparedData = _.chain(sortedData)
  .groupBy("placeId")
  .sortBy(item => sortedData.indexOf(item[0]))
  .map((value, key) => ({ place: value[0].placeId, data: value }))
  .value()

console.log(uiPreparedData)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>