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

JAVASCRIPT按一组连续值对数组重新排序,javascript,arrays,sorting,grouping,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, nam

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

我有一系列的项目:

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个项目的“组”对数组进行排序


你知道一个聪明的方法吗?我不知道从哪里开始…

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

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 } ]
  • 步骤1:分组
  • 步骤2:按id对每个组进行排序
  • 步骤3:从每个组中弹出以生成结果数组
例如:

我已经洗牌了您的
项目
,以确认分组是按id的升序进行的,即使不在源位置

项目=[
{id:1,名称:“test1”,组:1},
{id:3,名称:“test3”,组:2},
{id:4,名称:“test4”,组:2},
{id:6,名称:“Test 6”,组:2},
{id:2,名称:“test2”,组:2},
{id:9,名称:“test9”,组:1},
{id:10,名称:“Test 10”,组:3},
{id:5,名称:“测试5”,组:1},
{id:7,名称:“test7”,组:1},
{id:8,名称:“test8”,组:3}
];
var grouped=u.groupBy(项、函数(obj){
返回对象组;
});
对于(分组中的var索引){
var attr=分组[索引];
属性排序(函数(a,b){
返回(a.id-b.id);
});
}
var-res=[];
对于(变量i=0;i0){
res.push(分组[index].shift());
};
}
}
控制台日志(res)

对于相当小的数据集,您可能需要使用一个简单的算法,例如下面的算法。不过,请记住,
findIndex()
splice()
是非常昂贵的方法

var项目=[
{id:1,名称:“test1”,组:1},
{id:2,名称:“test2”,组:2},
{id:3,名称:“test3”,组:2},
{id:4,名称:“test4”,组:2},
{id:5,名称:“测试5”,组:1},
{id:6,名称:“Test 6”,组:2},
{id:7,名称:“test7”,组:1},
{id:8,名称:“test8”,组:3},
{id:9,名称:“test9”,组:1},
{id:10,名称:“Test 10”,组:3}
],
组=[
{id:1,名称:“组1”},
{id:2,名称:“组2”},
{id:3,名称:“组3”}
];
var res=[],i,n;
对于(n=0;items.length;n=(n+1)%groups.length){
if((i=items.findIndex(函数(v){return v.group==groups[n].id;}))!=-1){
再推(项目拼接(i,1));
}
}
//显示格式化输出
log(JSON.stringify(res.split('}],').join('}],\n'))
设想一个网格,其中的列表示您的组。如果你现在一行一行地展开这个网格,你就会得到你想要的顺序。有点像smarx解释的:组和zip

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

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

Edit:我不确定这是否完全清楚,但这段代码的大部分是按计算值排序的,因此如果您使用一些支持此功能的库,例如lodash,可以将其缩短为:

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

你的出发点是什么point@epascarello我看不出这个问题有什么帮助。@smarx真的吗?这似乎是在公然谈论这个话题。。按子属性对对象数组排序?您可以尝试使用相同的比较方法来实现排序算法。@dckuehn但此处的排序不是按属性进行的。。。目标是在各组之间交替(对于较小的组,根据需要跳过)。我可能只是错过了建议的算法,现在有两个人说它是相关的。如果你能想到一种方法,在这里使用带有自定义比较器的
排序
,你介意把它作为一个答案吗?@smarx好吧,我显然误解了这个问题。我看错了预期的结果。我确实认为实现排序仍然是可能的,但我必须比我想象的更多地考虑它。可能很有趣!
//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);
var positionsByGroupId = {}, numGroups = groups.length;
_.forEach(groups, ({id}, i) => { positionsByGroupId[id] = i });
_.sortBy(items, item => positionsByGroupId[ item.group ] += numGroups);