通过python在列表中查找不同的对
我有一个列表,我想在列表中找到不同的一对。 我实现了一个函数-->different() 还有其他更好的方法吗? 我想改进我的功能。通过python在列表中查找不同的对,python,performance,numpy,Python,Performance,Numpy,我有一个列表,我想在列表中找到不同的一对。 我实现了一个函数-->different() 还有其他更好的方法吗? 我想改进我的功能。 列表大小可能大于100000。使用列表 def different(array): return [[(x1, y1), (x2, y2)] for (x1, y1), (x2, y2) in array if (x1, y1) != (x2, y2)] 尝试使用过滤器: import numpy as np def different(array):
列表大小可能大于100000。使用列表
def different(array):
return [[(x1, y1), (x2, y2)] for (x1, y1), (x2, y2) in array if (x1, y1) != (x2, y2)]
尝试使用
过滤器
:
import numpy as np
def different(array):
return list(filter(lambda x: x[0]!=x[1],array.tolist()))
a = np.array([[[1, 2], [3, 4]],
[[1, 2], [1, 2]],
[[7, 9], [6, 3]],
[[3, 3], [3, 3]]])
out = different(a)
print(out)
最简单的方法是
import numpy as np
a = np.array([[[1, 2], [3, 4]],
[[1, 2], [1, 2]],
[[7, 9], [6, 3]],
[[3, 3], [3, 3]]])
b = np.logical_or(a[:,0,0] != a[:,1,0], a[:,0,1] != a[:,1,1])
print(a[b])
矢量化比较
这是通过获取每个子阵列的第一对并将每个子阵列与第二对进行比较来实现的。将选择所有子阵列,这些子阵列的条目仅不相同。考虑,
a[:, 0] == a[:, 1]
array([[False, False],
[ True, True],
[False, False],
[ True, True]])
因此,我们需要那些在每一列中都没有True的行。因此,在这个结果上,使用all
,然后对结果求反
~(a[:, 0] == a[:, 1]).all(1)
array([ True, False, True, False])
这将为您提供一个遮罩,您可以使用它从a
中选择子阵列
np.logical\u或.reduce
类似于上面的第一个选项,但从另一端处理这个问题(参见DeMorgan定律)
解决方案时间比较
当一个问题有这么多不同的解决方法时,时间比较确实有助于找出更好的答案
安装程序
我们使用了一个大小为(200000,2,2)
的数组,正如所指出的,它在预期数组大小的范围内
a = np.array(np.random.randint(10, size=(200000, 2, 2)))
使用答案:
使用第一个答案:矢量化比较
使用第二个答案:
使用答案:过滤器
使用答案:过滤器
结论
乔的方法是最快的。可以预见的是,每一种完整的python方法都远远不够numpy。通过在一行中使用列表理解,我们可以做到如下所示:
items_list = [[[1, 2], [3, 4]],
[[1, 2], [1, 2]],
[[7, 9], [6, 3]],
[[3, 3], [3, 3]]
]
# Output
[itm for itm in items_list if itm[0] != itm[1]]
我想过滤重复的配对列表有多大?根据列表的大小,有不同的方法。另外-您想要重复或不同的对?结果必须是元组吗?列表大小可能大于100,000@user3483203结果也可以存储在numpy阵列中。这是速度最快的一个@coldspeed,由于山崩,我正在运行一批timeit测试。5分钟,结果就出来了。@LucaCappelletti,也碰巧对索引进行了硬编码,并且只对具有两列的数组有效?好吧,如果是这样的情况,那就好了。我绝对不是说你的答案不好,我投你一票,我自己也投了,我只是被速度差吓坏了@乔的答案以微秒为单位,你的答案以毫秒为单位。它的速度慢了x20倍。此解决方案无法将
[[1,2],[1,3]]
识别为不同,而OP确实标记了它。您是对的,逻辑和
必须是逻辑或
。修正了。我相信被接受的答案应该是,因为这是一个最有效的答案。这只是一个答案比较。谢谢你!如果你要提交的答案只是对其他人代码的计时,真的应该像一个社区维基一样。在Joe的答案上,你也在计时面具的创建,而不是索引itself@user3483203好的,我会尽快修好的,对不起。如果可能的话,你能解释一下这是如何成为维基的吗?我从来没有写过。此外,这被认为是一种答案比较,有助于辨别哪些答案是最好的。请在投票时解释原因。如果答案有问题,我和阅读它的人都会从中受益,以便纠正错误。np.logical\u或.reduce
在我看来似乎是最好的解决方案,因为它是最快的,与具有部分不同对列表的OP函数具有相同行为。
a[np.logical_or.reduce(a[:, 0] != a[:, 1], axis=1)]
a = np.array(np.random.randint(10, size=(200000, 2, 2)))
%timeit b = a[np.logical_and(a[:,0,0] != a[:,1,0], a[:,0,1] != a[:,1,1])]
>>> 5.12 ms ± 110 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit b = a[~(a[:, 0] == a[:, 1]).all(1)]
>>> 13.7 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit b = a[np.logical_or.reduce(a[:, 0] != a[:, 1], axis=1)]
>>> 13.2 ms ± 498 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit b = list(filter(lambda x: x[0]!=x[1],a.tolist()))
>>> 102 ms ± 4.02 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit b = [[(x1, y1), (x2, y2)] for (x1, y1), (x2, y2) in a if (x1, y1) != (x2, y2)]
>>> 752 ms ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
items_list = [[[1, 2], [3, 4]],
[[1, 2], [1, 2]],
[[7, 9], [6, 3]],
[[3, 3], [3, 3]]
]
# Output
[itm for itm in items_list if itm[0] != itm[1]]