列表的python交集,但索引不相同

时间:2019-01-28 19:26:31

标签: python

我有一个奇怪的案例,过了一段时间我还没有想出足够的解决方案。

假设您有两个列表,则需要查找具有相同索引的项目。

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]

预先感谢

3 个答案:

答案 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

此版本逐项遍历第一个列表,并检查该项是否也在第二个列表中。如果是,它将比较两个列表中找到的项目的索引,如果索引不同,则将两个索引和项目值存储为一个元组,并在结果列表中包含三个值。