这里有一个列表:
a = [("ax", 1), ("ec", 3), ("bk", 5)]
另一个列表:
b = ["ec", "ax", "bk"]
我想要按照b
对a
进行排序:
sort_it(a, b)
a = [("ec", 3), ("ax", 1), ("bk", 5)]
如何做到这一点?
这里有一个列表:
a = [("ax", 1), ("ec", 3), ("bk", 5)]
另一个列表:
b = ["ec", "ax", "bk"]
我想要按照b
对a
进行排序:
sort_it(a, b)
a = [("ec", 3), ("ax", 1), ("bk", 5)]
如何做到这一点?
a.sort(key=lambda x: b.index(x[0]))
这将使用b
中每个元组的第一个元素在a
中查找其索引值,并以此为排序依据,对a
进行原地排序。
另一种可能更清晰的写法是:
a.sort(key=lambda (x,y): b.index(x))
如果你有大量的项目,可能更有效率的做法是稍微改变一下方式,因为在长列表上,.index()
可能是一个昂贵的操作,而且你实际上并不需要进行完全排序,因为你已经知道了顺序。mapping = dict(a)
a[:] = [(x,mapping[x]) for x in b]
注意,这仅适用于2元组列表。如果您希望它适用于任意长度的元组,您需要稍微修改一下:
mapping = dict((x[0], x[1:]) for x in a)
a[:] = [(x,) + mapping[x] for x in b]
TypeError: unhashable type: 'list'
- Trecta
进行排序,根据b
对索引进行排序,然后根据索引对a
进行排序。a.sort(key=lambda x: x[0])
ind = [i[0] for i in sorted(enumerate(b),key=lambda x: x[1])]
a = [i[0] for i in sorted(zip(a,ind),key=lambda x: x[1])]
由于每个排序都需要n*log(n),因此对于更大的列表仍然具有可扩展性。
实际上,有一种方法可以在线性O(n)时间内完成这个操作,因为这不是真正的排序操作。列表b的存在意味着排序已经完成了;我们真正需要做的就是重新排列a
中的元素以使其按照相同的顺序排列。这可以通过使用字典来高效地完成。
from collections import defaultdict
def sorted_by(seq_to_sort, desired_order, key=None):
if key is None:
key = lambda x: x
# group the elements by their key
grouped_items = defaultdict(list)
for item in seq_to_sort:
k = key(item)
grouped_items[k].append(item)
# flatten the dict of groups to a list
return [item for key in desired_order for item in grouped_items[key]]
使用方法:
a = [("ax", 1), ("ec", 3), ("bk", 5)]
b = ["ec", "ax", "bk"]
result = sorted_by(a, b, lambda tup: tup[0])
print(result) # output: [("ec", 3), ("ax", 1), ("bk", 5)]
This is a stable sort; if two list items have the same key, their order will be preserved. Example:
>>> sorted_by([1, 2, 3], [5], key=lambda x: 5)
[1, 2, 3]
If any list elements are mapped to keys that don't exist in desired_order
, those elements are silently discarded. For example:
>>> sorted_by([1, 2, 3], [1, 2, 3], key=lambda x: 5)
[]
See also:
desired_order
中包含重复元素的情况?例如,sorted_by([('a', 1), ('a', 2), ('b', 3), ('c', 4)], ['a', 'b', 'c', 'a'], key=lambda tup: tup[0])
应该返回 [('a', 1), ('b', 3), ('c', 4), ('a', 2)]
或 [('a', 2), ('b', 3), ('c', 4), ('a', 1)]
,其中一个 ('a', _)
元组映射到一个 'a'
键,而另一个元组映射到另一个键。 - Stef传统排序可能不是必要的。
[tup for lbl in b for tup in a if tup[0] == lbl]
# [('ec', 3), ('ax', 1), ('bk', 5)]