我得到了一些数据,需要创建一个排序映射。实际的排序是由C代码完成的,它从我的代码中获取整数列表flt_neworder
。这是我目前的解决方案:
# Demo data
data = [
"Option A", # 0
"Option B", # 1
"Blabla", # 2
"Some text" # 3
]
class Item:
def __init__(self, label):
self.label = label
col = [Item(d) for d in data]
# Create sorting mapping
flt_neworder = [
x[1] for x in sorted(
zip(
[x[0] for x in sorted(enumerate(col), key=lambda x: x[1].label)],
range(len(col))
)
)
]
# Output: [1,2,0,3]
print(flt_neworder)
所需输出:[1,2,0,3]
,不[2,0,1,3]
!
Position inflt_neworder
=项目在col
中的原始索引
整数值=新位置
什么是更有效的,或者至少是可读性更好的解决方案?你知道吗
我成功地测试了这一行:
tuple({k: i for i, (k, v) in enumerate(sorted(enumerate(data), key=operator.itemgetter(1)))}.values())
但是它仍然很难阅读,我相信我正在利用一个事实,即在CPython实现中dict
是被排序的。。。你知道吗
编辑
我想出了另一个解决办法:
flt_neworder = [None] * len(col)
for j, (_, i) in enumerate(sorted(zip((item.label for item in col), range(len(col))))): flt_neworder[i] = j
还有一个,但很慢:
flt_neworder = list(map(get(0), sorted(enumerate(sorted(enumerate(item.label for item in col), key=get(1))), key=get(1))))
感谢Ryan p提供了替代解决方案和测试时间的脚本!你知道吗
我在一个大数据集(1k个唯一字符串,full script)上测试了这些解决方案,与Ryan的小数据集相比,它们在计时上有着惊人的差异:
orig: 2.116799074272876
origmod: 2.118176033553482
orignew: 1.1691872433702883
orig3: 1.4400411206224817
orig4: 2.0643228139915664
rewrite: 26.06907118537356
rewriteop: 25.91357442379376
rewriteuniq: 10.783081019086694
赢家是orignew()
,而rewriteuniq()
对于小型数据集来说速度很快,但对于大型数据集来说却不是很好。你知道吗
这比原始代码更快,更易于阅读:
timeit
结果:(origmod类似于原始代码,但是没有
Item
类,因为它看起来不像您使用它;orignew是您的一行代码)你的一行稍微快一点,但我觉得读起来更难。你知道吗
好的,这次我将包含完整的测试代码。我把
Item
的创建从orig
移走了,因为创建这些只是为了模拟真实世界的数据。除了orig3
(您的新代码)和rewriteop
(rewrite
与operator.itemgetter
)之外,我还添加了一个额外的测试rewriteuniq
,以避免字符串是唯一的。你知道吗结果:
代码:
相关问题 更多 >
编程相关推荐