4

迭代一对可迭代对象a并按b排序顺序的一种方法(最快的方法?)是将它们链接起来并对链接的可迭代对象进行排序:

for i in sorted(chain(a, b)):
    print i

例如,如果每个迭代的元素是:

a: 4, 6, 1
b: 8, 3

那么这个构造将按顺序生成元素

1, 3, 4, 6, 8

但是,如果可迭代对象遍历对象,则会按对象的内存地址对对象进行排序。假设每个可迭代对象都迭代相同类型的对象,

  1. 迭代对象的特定属性(按此属性排序 )的最快方法是什么?

  2. 如果要选择的属性在可迭代对象之间不同怎么办?如果 iterablesab两者都迭代 type 的对象foo,这些对象具有相同类型的属性foo.xfoo.y那么如何迭代asorted byxbsorted by的元素y

对于 #2 的示例,如果

a: (x=4,y=3), (x=6,y=2), (x=1,y=7)
b: (x=2,y=8), (x=2,y=3)

那么元素应该按顺序生成

1, 3, 4, 6, 8

和以前一样。请注意,只有来自的x属性a和来自的y属性才能b进入排序和结果。

4

2 回答 2

3

Tim Pietzcker 已经回答了您对每个可迭代对象使用相同属性的情况。如果您使用相同类型的不同属性,您可以这样做(使用复数作为具有相同类型的两个属性的现成类):

在 Python 2 中:

>>> a = [1+4j, 7+0j, 3+6j, 9+2j, 5+8j]
>>> b = [2+5j, 8+1j, 4+7j, 0+3j, 6+9j]
>>> keyed_a = ((n.real, n) for n in a)
>>> keyed_b = ((n.imag, n) for n in b)
>>> from itertools import chain
>>> sorted_ab = zip(*sorted(chain(keyed_a, keyed_b), key=lambda t: t[0]))[1]
>>> sorted_ab
((1+4j), (8+1j), (3+6j), 3j, (5+8j), (2+5j), (7+0j), (4+7j), (9+2j), (6+9j))

由于在 Python 3 中zip()返回一个迭代器,我们需要在尝试对其下标之前将其强制为一个列表:

>>> # ... as before up to 'from itertools import chain'
>>> sorted_ab = list(zip(*sorted(chain(keyed_a, keyed_b), key=lambda t: t[0])))[1]
>>> sorted_ab
((1+4j), (8+1j), (3+6j), 3j, (5+8j), (2+5j), (7+0j), (4+7j), (9+2j), (6+9j))
于 2013-07-13T20:52:10.073 回答
2

对问题 1 的回答:您可以为 提供一个key属性sorted()。例如,如果您想按对象的 排序.name,则使用

sorted(chain(a, b), key=lambda x: x.name)

至于问题 2:我想您需要为每个foo.z可以访问的对象(如 Zero Piraeus 所建议的)提供另一个属性sorted(),因为该函数无法告诉它当前排序的对象来自哪里。毕竟,它正在接收一个新的迭代器,chain()其中不包含有关当前元素是 froma还是的任何信息b

于 2013-07-13T20:22:59.787 回答