JAVASCRIPT按一组连续值重新排序数组

时间:2016-07-27 18:53:11

标签: javascript arrays sorting grouping

我正在寻找一种通过一组连续的固定值对数组进行重新排序的方法。例如:

我有一系列项目:

items = [
  {id: 1, name: "Test 1", group: 1},
  {id: 2, name: "Test 2", group: 2},
  {id: 3, name: "Test 3", group: 2},
  {id: 4, name: "Test 4", group: 2},
  {id: 5, name: "Test 5", group: 1},
  {id: 6, name: "Test 6", group: 2},
  {id: 7, name: "Test 7", group: 1},
  {id: 8, name: "Test 8", group: 3},
  {id: 9, name: "Test 9", group: 1},
  {id: 10, name: "Test 10", group: 3}
];

我也知道我有三组:

groups = [
  {id: 1, name: "Group 1"},
  {id: 2, name: "Group 2"},
  {id: 3, name: "Group 3"}
];

我想做的事情就是这样:

new_array = [
 {id: 1, name: "Test 1", group: 1},
 {id: 2, name: "Test 2", group: 2},
 {id: 8, name: "Test 8", group: 3},
 {id: 5, name: "Test 5", group: 1},
 {id: 3, name: "Test 3", group: 2},
 {id: 10, name: "Test 10", group: 3}
 {id: 7, name: "Test 7", group: 1},
 {id: 4, name: "Test 4", group: 2},
 {id: 9, name: "Test 9", group: 1},
 {id: 6, name: "Test 6", group: 2},
];

我想按照第1,2,3组的顺序按照3个项目的“组”对数组进行排序

你知道这样做的聪明方法吗?我不知道从哪里开始...

4 个答案:

答案 0 :(得分:0)

var items = [
  {id: 1, name: "Test 1", group: 1},
  {id: 2, name: "Test 2", group: 2},
  {id: 3, name: "Test 3", group: 2},
  {id: 4, name: "Test 4", group: 2},
  {id: 5, name: "Test 5", group: 1},
  {id: 6, name: "Test 6", group: 2},
  {id: 7, name: "Test 7", group: 1},
  {id: 8, name: "Test 8", group: 3},
  {id: 9, name: "Test 9", group: 1},
  {id: 10, name: "Test 10", group: 3}
];

// grouped will map group IDs to arrays of items
// e.g. { '1': [ { id: 1, name: 'Test 1', group: 1 }, ... ], '2': ... }
var grouped = {};

for (var i = 0; i < items.length; i++) {
  var item = items[i];
  if (grouped[item.group] === undefined) {
    grouped[item.group] = [];
  }
  grouped[item.group].push(item);
}

// definition of groups and their order
var groups = [
  {id: 1, name: "Group 1"},
  {id: 2, name: "Group 2"},
  {id: 3, name: "Group 3"}
];

// we'll start with the first group
var groupIndex = 0;

var output = [];
for (var i = 0; i < items.length; i++) {
  // skip any empty groups
  while (grouped[groups[groupIndex].id].length === 0) {
    groupIndex = (groupIndex + 1) % groups.length;
  }

  // pull the first item from the group and add it to our output
  output.push(grouped[groups[groupIndex].id].shift());

  // move to the next group
  groupIndex = (groupIndex + 1) % groups.length;
}

console.log(output);
// Output:
// [ { id: 1, name: 'Test 1', group: 1 },
//   { id: 2, name: 'Test 2', group: 2 },
//   { id: 8, name: 'Test 8', group: 3 },
//   { id: 5, name: 'Test 5', group: 1 },
//   { id: 3, name: 'Test 3', group: 2 },
//   { id: 10, name: 'Test 10', group: 3 },
//   { id: 7, name: 'Test 7', group: 1 },
//   { id: 4, name: 'Test 4', group: 2 },
//   { id: 9, name: 'Test 9', group: 1 },
//   { id: 6, name: 'Test 6', group: 2 } ]

修改

这是另一种解决方案,使用lodash

var grouped = _.groupBy(items, function (item) { return item.group; });
var groupLists = _.map(groups, function (group) { return grouped[group.id]; });
var output = _.filter(_.flatten(_.zip.apply(null, groupLists)));
console.log(output);

答案 1 :(得分:0)

使用下划线进行分组的解决方案。

  • 第1步:分组
  • 第2步:按ID
  • 对每个组进行排序
  • 第3步:从每个组弹出以生成数组

实施例

我已经对你的items进行了改组,以确认即使不在源头,也会按照id的升序进行分组。

&#13;
&#13;
items = [
  {id: 1, name: "Test 1", group: 1},
  {id: 3, name: "Test 3", group: 2},
  {id: 4, name: "Test 4", group: 2},
  {id: 6, name: "Test 6", group: 2},
  {id: 2, name: "Test 2", group: 2},
  {id: 9, name: "Test 9", group: 1},
  {id: 10, name: "Test 10", group: 3},
  {id: 5, name: "Test 5", group: 1},
  {id: 7, name: "Test 7", group: 1},
  {id: 8, name: "Test 8", group: 3}
];
var grouped = _.groupBy(items, function(obj) {
  return obj.group;
});

for (var index in grouped) {
  var attr = grouped[index];
  attr.sort(function(a, b) {
    return (a.id - b.id);
  });
}
var res = [];
for (var i = 0; i < items.length; i++) {
  for (var index in grouped) {
    if (grouped[index].length > 0) {
      res.push(grouped[index].shift());
    };

  }
}
console.log(res);
&#13;
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

对于相当小的数据集,您可能希望使用诸如此类的简单算法。请记住,findIndex()splice()是相当昂贵的方法。

var items = [
      {id: 1,  name: "Test 1",  group: 1},
      {id: 2,  name: "Test 2",  group: 2},
      {id: 3,  name: "Test 3",  group: 2},
      {id: 4,  name: "Test 4",  group: 2},
      {id: 5,  name: "Test 5",  group: 1},
      {id: 6,  name: "Test 6",  group: 2},
      {id: 7,  name: "Test 7",  group: 1},
      {id: 8,  name: "Test 8",  group: 3},
      {id: 9,  name: "Test 9",  group: 1},
      {id: 10, name: "Test 10", group: 3}
    ],
    groups = [
      {id: 1, name: "Group 1"},
      {id: 2, name: "Group 2"},
      {id: 3, name: "Group 3"}
    ];

var res = [], i, n;

for(n = 0; items.length; n = (n + 1) % groups.length) {
  if((i = items.findIndex(function(v) { return v.group == groups[n].id; })) != -1) {
    res.push(items.splice(i, 1));
  }
}

// displaying formatted output
console.log(JSON.stringify(res).split('}],').join('}],\n'));

答案 3 :(得分:0)

//init positions by groupId
var positionsByGroupId = {}, numGroups = groups.length;
groups.forEach(({id}, i) => { positionsByGroupId[id] = i });

//compute the position of each item in the sorted Array.
//compose the item with the computed value we are sorting by
items.map(item => {
    return {
        value: item,
        //get value and update the index for this group
        //since we use this value only for sorting, it doesn't matter 
        //that it is actually offset by one row
        position: positionsByGroupId[ item.group ] += numGroups 
    }
})
//sort by the position, to get the right order
.sort((a, b) => a.position - b.position)
//return the ordered items
.map(obj => obj.value);

想象一个网格,其中列代表您的组。如果您现在逐行展开此网格,则会获得您要求的订单。有点像smarx解释:组和拉链。

但是我们可以在没有实际分组项目的情况下做到这一点,因为我们可以在输出中将它们的索引计算为col + row * numColumns。 由于列可能没有完全填充,这些位置可能与实际输出索引不匹配,但我们仍然可以使用它们来确定项目的顺序。

但是我们如何知道每个项目的位置,输入数组被洗牌。我们按列存储索引,并在迭代输入数组时跟踪/更新这些索引,方法是将该组的索引递增列数/组。

编辑:我不确定这是否完全清楚,但是这段代码的大部分都是按计算值排序的,所以如果你使用一些支持它的lib,就像例如,你可以将它缩短为:

var positionsByGroupId = {}, numGroups = groups.length;
_.forEach(groups, ({id}, i) => { positionsByGroupId[id] = i });
_.sortBy(items, item => positionsByGroupId[ item.group ] += numGroups);