【发布时间】:2011-02-11 23:34:12
【问题描述】:
试图找到一种有效的方法来从另一个数组中提取所有项的实例。
例如
array1 = ["abc", "def", "ghi", "jkl"]
array2 = ["abc", "ghi", "456", "789"]
数组1是需要从数组2中提取出来的一个数组,因此数组2应该修改为["456", "789"]
我知道如何做到这一点,但没有有效的方式。
【问题讨论】:
试图找到一种有效的方法来从另一个数组中提取所有项的实例。
例如
array1 = ["abc", "def", "ghi", "jkl"]
array2 = ["abc", "ghi", "456", "789"]
数组1是需要从数组2中提取出来的一个数组,因此数组2应该修改为["456", "789"]
我知道如何做到这一点,但没有有效的方式。
【问题讨论】:
如果您的列表不能包含重复项并且您不关心顺序,那么您应该使用集合而不是列表(顺便说一下,它们被称为列表,而不是数组)。那么你想要的就是实现起来既快速又简单:
>>> set1 = set(["abc", "def", "ghi", "jkl"])
>>> set2 = set(["abc", "ghi", "456", "789"])
>>> set2 - set1
set(['456', '789'])
如果 list2 可以包含重复项或顺序很重要,那么您仍然可以将 list1 设置为一组以加快查找速度:
>>> list1 = ["abc", "def", "ghi", "jkl"]
>>> list2 = ["abc", "ghi", "456", "789"]
>>> set1 = set(list1)
>>> [a for a in list2 if a not in set1]
['456', '789']
请注意,这要求项目是可散列的,但运行时间接近 O(n)。
如果项目不可散列但它们是可排序的,那么您可以对 list1 进行排序并使用二进制搜索来查找其中的项目。这给了 O(n log(n)) 时间。
如果您的项目既不可散列也不可订购,那么您将需要对每个元素使用缓慢的 O(n*n) 简单线性搜索。
【讨论】:
list2 应该是一个集合,可能list1 也是。
这些是列表,而不是数组。 (“数组”这个词对不同的人意味着不同的东西,但在 python 中,对象称自己为列表,仅此而已;还有其他模块提供称自己为数组的对象,例如 array 和 numpy)
要回答您的问题,最简单的方法是根本不修改 array2。使用列表推导:
set1 = set(array1)
array2 = [e for e in array2 if e not in set1]
(这个集合使得这个 O(n) 而不是 O(n^2))
如果你绝对必须改变array2(因为它存在于其他地方),你可以使用切片赋值:
array2[:] = [e for e in array2 if e not in set1]
它同样有效,但有点讨厌。
edit:正如 Mark Byers 所指出的,这仅适用于 array1 仅包含可散列元素(如字符串、数字等)的情况。
【讨论】:
set(array2) - set(array2)。
直接的方法是这样的;
array2 = [i for i in array2 if i not in array1]
这里需要列表推导
【讨论】: