使用itemgetter或比Lambda更快的方法按元组n个元素对嵌套元组列表进行排序

时间:2019-03-11 13:38:34

标签: python sorting

我有很多代码在对嵌套元组的列表进行排序上,因此大部分的运行时间都花在了排序上。 ALTER PROCEDURE [dbo].[SelectItem] @identifier VARCHAR(200) AS BEGIN SELECT tb_Items_Master.item_auto_code AS 'Item Code', tb_Items_Master.item_name_en AS 'Item Name', MIN(tb_Quantity_Expire.expity_date) AS 'Expiry', SUM(tb_Quantity_Expire.quantity) AS 'Stock', tb_Items_Master.price AS 'Price' FROM (tb_Items_Master INNER JOIN tb_Quantity_Expire ON tb_Items_Master.item_auto_code = tb_Quantity_Expire.item_auto_code LEFT JOIN tb_Items_Codes ON tb_Items_Master.item_auto_code = tb_Items_Codes.item_auto_code) WHERE tb_Items_Codes.item_code = @identifier OR tb_Items_Master.item_name_en LIKE '%'+@identifier+'%' OR tb_Items_Master.item_name_2 LIKE '%'+@identifier+'%' -- I'm calling it in the following line OR tb_Items_Master.item_auto_code = SELECT dbo.TryConvertInt(@identifier) GROUP BY tb_Items_Master.item_auto_code, tb_Items_Master.item_name_en, tb_Items_Master.price; END 加快了简单排序的速度,但是似乎无法弄清楚其实现对嵌套元组n项进行排序的实现,例如,operator.itemgetter方法有效。

以下示例数据;

list.sort(key = lambda x: x[1][n])

如果我想按每个元组的第二个项目(在这种情况下为元组)排序;

import random

v1 = random.sample(range(1, 100), 10)
v2 = random.sample(range(1, 100), 10)
v3 = random.sample(range(1, 100), 10)
v4 = random.sample(range(1, 100), 10)
out = zip(v1, zip(v2, v3, v4))
[(18, (68, 11, 71)),
 (72, (24, 3, 79)),
 (2, (1, 84, 69)),
 (24, (94, 79, 17)),
 (19, (67, 76, 19)),
 (44, (79, 12, 34)),
 (42, (11, 33, 92)),
 (90, (18, 52, 47)),
 (65, (73, 59, 70)),
 (95, (74, 85, 60))]

如果我想按每个元组的第二个元素(在本例中为一个元组)排序,并且我可以使用该第二个元素;

import operator
out.sort(key = operator.itemgetter(1))
[(2, (1, 84, 69)),
 (42, (11, 33, 92)),
 (90, (18, 52, 47)),
 (72, (24, 3, 79)),
 (19, (67, 76, 19)),
 (18, (68, 11, 71)),
 (65, (73, 59, 70)),
 (95, (74, 85, 60)),
 (44, (79, 12, 34)),
 (24, (94, 79, 17))]

可以使用out.sort(key = lambda x: x[1][1]) [(72, (24, 3, 79)), (18, (68, 11, 71)), (44, (79, 12, 34)), (42, (11, 33, 92)), (90, (18, 52, 47)), (65, (73, 59, 70)), (19, (67, 76, 19)), (24, (94, 79, 17)), (2, (1, 84, 69)), (95, (74, 85, 60))] 完成吗?谢谢。

1 个答案:

答案 0 :(得分:2)

AFAIK,itemgetter没有提供类似的模式。但是,您可以使用functools.partialreduce来定义自己的名称:

>>> from functools import *
>>> deep_get = lambda *indices: partial(reduce, lambda x, i: x[i], indices)
>>> deep_get(1, 1)(out[0])
89
>>> sorted(out, key=deep_get(1, 1))
[(27, (56, 12, 88)),
 (71, (9, 22, 25)),
 (54, (35, 24, 93)),
 (98, (44, 31, 48)),
 (55, (37, 55, 44)),
 (65, (93, 58, 81)),
 (13, (25, 68, 78)),
 (14, (96, 70, 38)),
 (66, (50, 86, 15)),
 (33, (52, 89, 83))]

请注意,虽然这比您的lambda ,但是对于不同级别的嵌套,它可能更具通用性。如果只是为了提高速度,您应该将lambda替换为一个“适当的”函数def get(x): return x[1][1],这似乎和itemgetter一样快(在我的系统上,对{{1}进行排序} out(一个级别)或itemgetter用1.3µs,def get用1.7µs,lambda用3µs)。

deep_get