我正在寻找一种通过一组连续的固定值对数组进行重新排序的方法。例如:
我有一系列项目:
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个项目的“组”对数组进行排序
你知道这样做的聪明方法吗?我不知道从哪里开始...
答案 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)
使用下划线进行分组的解决方案。
实施例
我已经对你的items
进行了改组,以确认即使不在源头,也会按照id的升序进行分组。
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;
答案 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);