是否有更好的方法通过嵌套元组值对列表进行排序,而不是编写提取嵌套元组值的itemgetter替代方法:
def deep_get(*idx):
def g(t):
for i in idx: t = t[i]
return t
return g
>>> l = [((2,1), 1),((1,3), 1),((3,6), 1),((4,5), 2)]
>>> sorted(l, key=deep_get(0,0))
[((1, 3), 1), ((2, 1), 1), ((3, 6), 1), ((4, 5), 2)]
>>> sorted(l, key=deep_get(0,1))
[((2, 1), 1), ((1, 3), 1), ((4, 5), 2), ((3, 6), 1)]
我考虑过使用compose,但这不在标准库中:
sorted(l, key=compose(itemgetter(1), itemgetter(0))
我在libs中遗漏了哪些内容可以使这段代码变得更好?
实施应该合理地使用100k项目。
上下文:我想对直方图项目的字典进行排序。键是元组(a,b),值是计数。最后,项目应按计数递减,a和b排序。另一种方法是展平元组并直接使用itemgetter,但这样会产生很多元组。
答案 0 :(得分:11)
是的,你可以使用key=lambda x: x[0][1]
答案 1 :(得分:2)
鉴于您拥有的数据结构,您的方法非常好。
另一种方法是使用另一种结构。
如果你想要速度,可以使用去因子标准NumPy。它的工作是有效地处理大型数组。它甚至为你的阵列提供了一些很好的排序程序。以下是您对计数进行排序的方法,然后是(a,b):
>>> arr = numpy.array([((2,1), 1),((1,3), 1),((3,6), 1),((4,5), 2)],
dtype=[('pos', [('a', int), ('b', int)]), ('count', int)])
>>> print numpy.sort(arr, order=['count', 'pos'])
[((1, 3), 1) ((2, 1), 1) ((3, 6), 1) ((4, 5), 2)]
这非常快(它在C中实现)。
如果你想坚持使用标准的Python,包含(count,a,b)元组的列表会自动按照你想要的方式排序(在元组上使用字典顺序)。
答案 2 :(得分:1)
这可能是您的方法的一个更快的版本:
l = [((2,1), 1), ((1,3), 1), ((3,6), 1), ((4,5), 2)]
def deep_get(*idx):
def g(t):
return reduce(lambda t, i: t[i], idx, t)
return g
>>> sorted(l, key=deep_get(0,1))
[((2, 1), 1), ((1, 3), 1), ((4, 5), 2), ((3, 6), 1)]
可以缩短为:
def deep_get(*idx):
return lambda t: reduce(lambda t, i: t[i], idx, t)
甚至只是简单地写出来:
sorted(l, key=lambda t: reduce(lambda t, i: t[i], (0,1), t))
答案 3 :(得分:0)
我比较了两种类似的解决方案。第一个使用简单的lambda:
def sort_one(d):
result = d.items()
result.sort(key=lambda x: (-x[1], x[0]))
return result
请注意x[1]
上的减号,因为您希望排序按计数递减。
第二个利用了Python中sort
稳定的事实。首先,我们按(a, b)
(升序)排序。然后我们按计数排序,降序:
def sort_two(d):
result = d.items()
result.sort()
result.sort(key=itemgetter(1), reverse=True)
return result
第一个快速增加10-20%(在小型和大型数据集上都有),并且在我的Q6600(使用一个核心)上完成不到0.5秒就可以获得100k项目。因此,避免创建元组似乎没什么帮助。