您的标题实际上比您的描述更清晰,可以直接翻译成代码:
根据另一个列表中是否存在项目对列表进行排序
代码:
>>> sorted(b, key=set(a).__contains__, reverse=True)
['30', '17', '60', '1201', '900']
或
>>> sorted(b, key=lambda x, s=set(a): x not in s)
['30', '17', '60', '1201', '900']
排序布尔值实际上与线性时间没有区别,并且这些解决方案比您的示例数据以及我尝试使用数百万个随机数的示例数据(其中大约一半 b 的元素)都比公认的解决方案更快在a)。
基准测试
n b in a kaya1 kaya2 heap1 heap2 heap3
----------------------------------------------------------
1024 53.12% 0.00046 0.00033 0.00020 0.00067 0.00018
2048 51.03% 0.00142 0.00069 0.00048 0.00071 0.00060
4096 50.34% 0.00226 0.00232 0.00127 0.00183 0.00125
8192 50.42% 0.00938 0.00843 0.00328 0.00471 0.00351
16384 50.38% 0.02010 0.01647 0.00776 0.00992 0.00839
32768 49.96% 0.03987 0.03165 0.01661 0.02326 0.01951
65536 50.20% 0.08002 0.06548 0.03326 0.04828 0.03896
131072 50.04% 0.16118 0.12863 0.06671 0.09642 0.07840
262144 50.06% 0.32698 0.26757 0.13477 0.19342 0.15828
524288 50.08% 0.66735 0.54627 0.27378 0.38365 0.32496
1048576 50.00% 1.34095 1.08972 0.54703 0.78028 0.65623
2097152 50.03% 2.68957 2.20556 1.13797 1.60649 1.33975
4194304 50.01% 5.36141 4.33496 2.25494 3.18520 2.70506
8388608 49.99% 10.72588 8.74114 4.56061 6.35421 5.36515
注意:
-
n 是 b 的大小。
-
a 在对功能进行基准测试之前准备为set,以便专注于它们的差异。 a 的大小始终为 8388608 以保持 in a 检查恒定时间(即使 sets 变大时会变慢)。
-
b in a 是b 的元素在a 中的百分比。我把它们做成了大约 50%。
-
kaya1 和 kaya2 来自@kaya3 接受的答案,经过修改以便他们完成我认为的任务(通过a 中的项目的存在对b 进行排序,而不是“a & b”后跟“ b \ a")。
-
heap1 和heap2 是我上面使用sorted 的两个解决方案。
-
heap3 是我能够编写的没有 sorted 的最快解决方案。
- 结果以秒为单位。
基准代码:
from timeit import repeat
import random
def kaya1(a_set, b):
return [*filter(lambda x: x in a_set, b), *filter(lambda x: x not in a_set, b)]
def kaya2(a_set, b):
return [*(x for x in b if x in a_set), *(x for x in b if x not in a_set)]
def heap1(a_set, b):
return sorted(b, key=a_set.__contains__, reverse=True)
def heap2(a_set, b):
return sorted(b, key=lambda x: x not in a_set)
def heap3(a_set, b):
not_in_a = []
append = not_in_a.append
in_a = [x for x in b if x in a_set or append(x)]
in_a.extend(not_in_a)
return in_a
print(' n b in a kaya1 kaya2 heap1 heap2 heap3')
print('----------------------------------------------------------')
A = random.sample(range(2**24), 2**23)
B = random.sample(range(2**24), 2**23)
a_set = set(A)
for e in range(10, 24):
n = 2**e
b = B[:n]
print('%7d %5.2f%%' % (n, 100 * len(set(b) & a_set) / len(b)), end='')
expect = None
for sort in kaya1, kaya2, heap1, heap2, heap3:
t = min(repeat(lambda: sort(a_set, b), number=1))
print('%9.5f' % t, end='')
output = sort(a_set, b)
if expect is None:
expect = output
else:
assert output == expect
print()