我有一个奇怪的案例,过了一段时间我还没有想出足够的解决方案。
假设您有两个列表,则需要查找具有相同索引的项目。
x = [1,4,5,7,8]
y = [1,3,8,7,9]
通过使用以下命令,我能够正确显示两个列表中具有相同索引的那些交叉点:
matches = [i for i, (a,b) in enumerate(zip(x,y)) if a==b)
这将返回:
[0,3]
我能够简单地将两个列表与以下列表相交(并且在许多其他方式下,这只是一个示例)
intersected = set(x) & set(y)
这将返回此列表:
[1,8,7,9]
这是问题。我想知道一些获取项目列表(如第二个列表)的方法的想法,这些列表不包括上面的那些匹配项,但不在列表中的相同位置。
换句话说,我正在寻找x中不共享y中相同索引的项目
期望的结果将是y的索引位置“ 8”或[2]
预先感谢
答案 0 :(得分:2)
您是如此亲密:遍历y
;寻找x
中的一个值,但不是在同一位置:
offset = [i for i, a in enumerate(y) if a in x and a != x[i] ]
结果:
[2]
针对pault
注释,包括从Martijn's
升级的建议...在大型列表的情况下,预处理可以降低复杂性:
>>> both = set(x) & set(y)
>>> offset = [i for i, a in enumerate(y) if a in both and a != x[i] ]
正如PaulT指出的那样,这在OP的发布级别上还是很容易理解的。
答案 1 :(得分:2)
我将为第一个列表创建一个索引字典,然后使用该字典来测试第二个值是否为a)该字典中的值,以及b)当前索引是否不存在:
def non_matching_indices(x, y):
x_indices = {}
for i, v in enumerate(x):
x_indices.setdefault(v, set()).add(i)
return [i for i, v in enumerate(y) if i not in x_indices.get(v, {i})]
以上操作需要O(len(x) + len(y))
时间;对一个列表进行一次完整扫描,然后对另一个列表进行另一个完整扫描,其中包含i
的每个测试均在固定时间内完成。
您真的不想在这里使用value in x
容纳测试,因为这需要对x
进行扫描(循环)以查看该值是否确实在列表中。这需要O(len(x))
时间,您需要为y
中的每个值执行此操作,这意味着功能需要O(len(x) * len(y))
时间。
当您运行包含大量随机数据的较大列表的计时赛时,您会看到速度差异:
>>> import random, timeit
>>> def using_in_x(x, y):
... return [i for i, a in enumerate(y) if a in x and a != x[i]]
...
>>> x = random.sample(range(10**6), 1000)
>>> y = random.sample(range(10**6), 1000)
>>> for f in (using_in_x, non_matching_indices):
... timer = timeit.Timer("f(x, y)", f"from __main__ import f, x, y")
... count, total = timer.autorange()
... print(f"{f.__name__:>20}: {total / count * 1000:6.3f}ms")
...
using_in_x: 10.468ms
non_matching_indices: 0.630ms
因此,如果有两个包含1000个数字的列表,那么如果您使用value in x
测试,则轻松地花费15倍的时间来完成任务。
答案 2 :(得分:-1)
fetched
此版本逐项遍历第一个列表,并检查该项是否也在第二个列表中。如果是,它将比较两个列表中找到的项目的索引,如果索引不同,则将两个索引和项目值存储为一个元组,并在结果列表中包含三个值。