首页 > 解决方案 > 对数组进行排序以对匹配元素进行分组但保持原始顺序

问题描述

我需要对一组对象进行排序,以便对具有相似类别的项目进行分组,但不会丢失类别的原始索引

我想按类别键排序/分组,但保持类别出现在数组中的顺序。类别没有特定的顺序。

arr = [
  {
    name: "Name 1",
    category: "D Category"
  },
  {
    name: "Name 2",
    category: "A Category"
  },
  {
    name: "Name 3",
    category: "D Category"
  },
  {
    name: "Name 4",
    category: "G Category"
  },
  {
    name: "Name 5",
    category: "A Category"
  }
];

尝试不太奏效,它最终将具有相同类别的项目放在一起但按字母顺序排列,我不想要

arr.sort((first, second) => {
      const firstId = first.category;
      const secondId = second.category;

      if (firstId < secondId) {
        return -1;
      }
      if (firstId > secondId) {
        return 1;
      }

      return 0;
});

预期结果:

expectedResult = [
  {
    name: "Name 1",
    category: "D Category"
  },
  {
    name: "Name 3",
    category: "D Category"
  },
  {
    name: "Name 2",
    category: "A Category"
  },
  {
    name: "Name 5",
    category: "A Category"
  },
  {
    name: "Name 4",
    category: "G Category"
  }
];

进行 .sort 比较部分适用于相似类别在一起但最终按字母顺序排列的情况,这是我不想要的

标签: javascriptarrays

解决方案


这是一种可能对您有用的方法。基本上,它会执行您正在尝试的操作,但会引入创建优先级映射的中间步骤。此映射将包含唯一category值(来自原始数据)作为键,它们出现的顺序作为值。然后,您可以简单地基sort于此逻辑。我的代码可能比我的解释更清楚:

//Original data
const arr = [{
  name: "Name 1",
  category: "D Category",
}, {
  name: "Name 2",
  category: "A Category"
}, {
  name: "Name 3",
  category: "D Category"
}, {
  name: "Name 4",
  category: "G Category"
}, {
  name: "Name 5",
  category: "A Category"
}];

// A priority map so we have a basis for sorting
const orderPriority = arr
  .map(o => o.category)
  .reduce((map, category, idx) => {
    if (map[category] == null) {
      map[category] = idx;
    }
    return map;
  }, {});

// Now implement the sort based on the priorty map we created:
arr.sort((a, b) => orderPriority[a.category] - orderPriority[b.category]);

console.log(arr);


推荐阅读