我有一个对象列表:
[ { id: 4, name:'alex' }, { id: 3, name:'jess' }, { id: 9, name:'...' }, { id: 1, name:'abc' } ]
我有另一个列表,其中包含正确的“订单”。
[ 3, 1, 9, 4]
如何根据键“id”将第一个列表与第二个列表的顺序相匹配? 结果应该是:
[ { id: 3, name:'jess' }, { id: 1, name:'abc' }, { id: 9, name:'...' }, { id: 4, name:'alex' } ]
答案 0 :(得分:26)
我介入了这个问题并用简单的.sort
假设您要排序的列表存储在变量needSort
中,并且带有顺序的列表位于变量order
中且两者都在同一范围内,您可以运行{{1像这样:
.sort
它对我有用,希望它有所帮助。
答案 1 :(得分:7)
嗯,简单的答案是,“对于一组这么小的数据,任何比无限循环更低成本的数据基本上都是不可察觉的。”但是,让我们试着回答这个“正确的问题。”
第二个数组中的顺序没有押韵或理由,它只是第一个数组主键上的外键列表(使用SQL术语)。因此,将它们视为键,并且我们希望有效地查找这些键,哈希表(对象)可能会以O(n)
方式(2*n
真正地“排序”这个最快的方式。假设第一个数组称为objArray
,第二个数组称为keyArray
:
// Create a temporary hash table to store the objects
var tempObj = {};
// Key each object by their respective id values
for(var i = 0; i < objArray.length; i++) {
tempObj[objArray[i].id] = objArray[i];
}
// Rebuild the objArray based on the order listed in the keyArray
for(var i = 0; i < keyArray.length; i++) {
objArray[i] = tempObj[keyArray[i]];
}
// Remove the temporary object (can't ``delete``)
tempObj = undefined;
那应该这样做。我想不出任何不需要两遍的方法。 (或者像这样一个接一个地,或者通过在数组中多次传递并splice
找出找到的元素,例如,对于向后排序的数据可能会花费很多。)
答案 2 :(得分:6)
我如何解决几乎相同的问题
data = [{ id: 4, name:'alex' }, { id: 3, name:'jess' }, { id: 9, name:'...' }, { id: 1, name:'abc' } ];
sorted = [3, 1, 9, 4].map((i) => data.find((o) => o.id === i));
答案 3 :(得分:2)
function sort(array, order) {
//create a new array for storage
var newArray = [];
//loop through order to find a matching id
for (var i = 0; i < order.length; i++) {
//label the inner loop so we can break to it when match found
dance:
for (var j = 0; j < array.length; j++) {
//if we find a match, add it to the storage
//remove the old item so we don't have to loop long nextime
//and break since we don't need to find anything after a match
if (array[j].id === order[i]) {
newArray.push(array[j]);
array.splice(j,1);
break dance;
}
}
}
return newArray;
}
var newOrder = sort(oldArray,[3, 1, 9, 4]);
console.log(newOrder);
答案 4 :(得分:1)
我认为您找到的最佳方法是使用id值作为属性名称将第一个列表的所有元素放入哈希值;然后通过迭代id列表构建第二个列表,查找哈希中的每个对象,并将其附加到列表中。
答案 5 :(得分:1)
将列表设为对象,而不是order = [3, 1, 9, 4]
,而是order = { 3:0, 1:1, 9:2, 4:3}
,然后执行以下操作
function ( order, objects ){
ordered_objects = []
for( var i in objects ){
object = objects[i]
ordered_objects[ order[ object.id ] ] = object
}
return ordered_objects
}
答案 6 :(得分:1)
有点像这样:
var data = [ { id: 4, name:'alex' }, { id: 3, name:'jess' }, { id: 9, name:'...' }, { id: 1, name:'abc' } ],
order = [ 3, 1, 9, 4],
sorted = [],
items = {},
i;
for (i = 0; i < data.length; i++)
items[data[i].id] = data[i];
for (i = 0; i < order.length; i++)
sorted.push(items[order[i]]);
我们的想法是使用id作为属性名称将data
中的项目放入对象中 - 这样您就可以检索具有给定ID的项目而无需搜索数组。 (否则你必须在单个循环中使用嵌套循环或Array.indexOf()
函数,就性能而言,它实际上将是一个嵌套循环。)
这假设data
中没有两个元素具有相同的id属性。
答案 7 :(得分:0)
你可以使用Alasql库和两个数组的简单SELECT JOIN来完成它。
唯一的一件事:Alasql将源数据理解为数组数组或对象数组,所以你 需要将简单数组转换为数组数组(参见步骤1)
var data1 = [ { id: 3, name:'jess' }, { id: 1, name:'abc' },
{ id: 9, name:'...' }, { id: 4, name:'alex' } ];
var data2 = [3, 1, 9, 4];
// Step 1: Convert [3,1,9,4] to [[3],[1],[9],[4]]
var data2a = data2.map(function(d){return [d]});
// Step 2: Get the answer
var res = alasql('SELECT data1.* FROM ? data1 JOIN ? data2 ON data1.id = data2.[0]',
[data1,data2a]);
试试这个例子at jsFiddle。
答案 8 :(得分:0)
# Failed Approach 1
df['listings'] = np.where(df['listings'].isnull(), ['none']*4, df['listings'])
# Failed Approach 2
df['listings'].fillna(['none']*4)