我有一个带有id的对象列表(object.id)和一个id列表。使用id列表排序对象列表的最有效方法是什么?我有以下解决方案......只是想知道是否有更快的解决方案?
输入:
result
=具有用户ID的用户对象列表(user.id)list_of_ids
=用户ID列表,例如[3, 2, 5, 8, 9]
输出:
list_of_ids
代码:
ordered_result = []
for user_id in list_of_ids:
for user in result:
if user_id == user.id:
ordered_result.append(user)
break
答案 0 :(得分:3)
您可以先将用户置于词典中:
usrdict = {}
for user in result:
usrdict[user.id] = user
然后,根据用户id
查找用户,您可以选择一些选项,例如:
ordered_result = [usrdict[x] for x in list_of_ids]
编辑:我可能,除非你有一个非常大的列表或执行很多次的操作,不要担心效率那么多,而是注重使其清晰可读。
答案 1 :(得分:1)
您可以使用sorted
功能和自定义排序功能。在这种情况下,在ids列表中返回索引。
def order_by(objects, ids):
def fn(obj):
return ids.index(obj["id"])
return sorted(objects, key=fn)
print(order_by(objects_list, id_list))
示例:
objects_list = [
{ "id": 3, "name": "penny"},
{ "id": 5, "name": "adam"},
{ "id": 9, "name": "meh"},
{ "id": 1, "name": "john"},
{ "id": 3, "name": "archibald"},
]
id_list = [9,1,3,5,6,4]
print(order_by(objects_list, id_list))
结果:
[{'id': 9, 'name': 'meh'}, {'id': 1, 'name': 'john'}, {'id': 3, 'name': 'penny'}, {'id': 3, 'name': 'archibald'}, {'id': 5, 'name': 'adam'}]
答案 2 :(得分:0)
这是一个O(n log(n))解决方案。它要求两个列表中的ID完全相同。它按id对对象列表进行排序,并对id列表进行间接排序,从而产生一个包含id的位置的索引列表。然后使用它将已排序的对象移动到正确的位置。
import operator
class know_who_you_are:
def __init__(self, id_):
self.id = id_
def argsort(L):
"returns sorted, order"
return zip(*sorted(zip(L, range(len(L)))))
ids = [3, 2, 4, 5, 1]
objs = [know_who_you_are(id_) for id_ in [1, 5, 3, 2, 4]]
sid, oid = argsort(ids)
sobj = sorted(objs, key=operator.attrgetter('id'))
result = len(objs) * [None]
for dest, src in zip(oid, sobj):
result[dest] = src
# check
print(all(id_==obj.id for id_, obj in zip(ids, result)))
打印:
True
答案 3 :(得分:0)
这里是使用带有自定义比较功能的内置sorted()
函数的方案的变体。 (它可能看起来像很多代码,但其中很大一部分仅用于设置一个有点现实的测试用例。)
from functools import cmp_to_key
import random
random.seed(13) # Gets consistent "random" ordering during testing.
class User:
def __init__(self, name, id):
self.name = name
self.id = id
def __repr__(self):
return '{}({!r}, id={!r})'.format(self.__class__.__name__, self.name, self.id)
@cmp_to_key # Converts cmp function to a key function.
def cmp(x, y):
""" Return -1 if the position of User x in list_of_ids < index of User y
otherwise return 1.
"""
p1, p2 = -1, -1
try:
p1 = list_of_ids.index(x.id)
p2 = list_of_ids.index(y.id)
except ValueError:
pass
return -1 if p1 < p2 else 1
list_of_ids = [3, 2, 5, 8, 9]
# Create a random list of users with these ids.
shuffled_ids = random.sample(list_of_ids, k=len(list_of_ids))
users = [User(name, id) for name, id in zip(['Andy', 'Simon', 'Nick', 'John',
'Roger'], shuffled_ids)]
print('Desired id order:', list_of_ids)
print()
print(' Before:', users)
ordered_result = sorted(users, key=cmp)
print('Ordered:', ordered_result)
输出:
Desired id order: [3, 2, 5, 8, 9]
Before: [User('Andy', id=5), User('Simon', id=9), User('Nick', id=8), User('John', id=3), User('Roger', id=2)]
Ordered: [User('John', id=3), User('Roger', id=2), User('Andy', id=5), User('Nick', id=8), User('Simon', id=9)]