我有以下代码来选择另一个列表中未包含的值。
import re
isbn = ["1111","2222","3333","4444","5555"]
sku = ["k1 1111", "k2 2222", "k3 3333", "k4 4444", "k5 5555", "k6 6666", "k7 7777", "k8 8888" ,"k9 1111"]
for x in isbn:
for i in sku:
if x not in i:
print (i)
预期结果应该是这样的:
k6 6666
k7 7777
k8 8888
但我得到了所有无与伦比的价值观。如上所示,我怎样才能得到预期的结果。
答案 0 :(得分:8)
您应该在循环中使用any
。事实上,您可以使用 list comprehension 下面的来实现它:
any
如果True
中的任何字符串作为list_1
中的子字符串出现,则list2
将返回True
。一旦找到匹配,它将使迭代(不检查其他匹配)短路,并将结果返回为any
。
如果您对使用for
不感兴趣,可以使用以下for x in list_2:
for y in list_1:
if y in x:
break
else:
print(x)
循环获得相同的结果:
k6 6666
k7 7777
k8 8888
将打印您想要的输出:
NR>1 {
if($1==p){
# Skip identical lines
next
}
if($1>p){
print "smaller"
}else{
print "greater"
}
}
# Store previous value
{p=$1}
答案 1 :(得分:2)
您需要在isbn
中测试所有值,然后才能得出这些值的匹配结果。
不是首先遍历isbn
,而是循环遍历sku
并使用每个isbn
值测试该值; any()
function使这更容易,更有效:
for value in sku:
if not any(i in value for i in isbn):
print(value)
更高效的仍然是拆分 ISBN部分,并针对集合进行测试:
isbn_set = set(isbn)
for value in sku:
isbn_part = value.partition(' ')[-1] # everything after the first space
if isbn_part not in isbn_set:
print(value)
这可以避免绕过isbn
altogther;集合成员测试需要O(1)恒定时间;对于N skus和M ISBN值,这会产生一个O(N)循环(与O {NM}循环any()
)。
任何一个版本都可以转换为list comprehension以生成匹配列表;然后首选的设置版本变为:
isbn_set = set(isbn)
not_matched = [value for value in sku if value.partition(' ')[-1] not in isbn_set]
后者的演示:
>>> isbn = ["1111","2222","3333","4444","5555"]
>>> sku = ["k1 1111", "k2 2222", "k3 3333", "k4 4444", "k5 5555", "k6 6666", "k7 7777", "k8 8888" ,"k9 1111"]
>>> isbn_set = set(isbn)
>>> [value for value in sku if value.partition(' ')[-1] not in isbn_set]
['k6 6666', 'k7 7777', 'k8 8888']
答案 2 :(得分:0)
如果你从一个集合中删除匹配,那么左边的集合就是你所追求的:
skus = set(sku)
for x in isbn:
skus -= {i for i in skus if x in i}
isbn = ["1111", "2222", "3333", "4444", "5555"]
sku = ["k1 1111", "k2 2222", "k3 3333", "k4 4444", "k5 5555", "k6 6666",
"k7 7777", "k8 8888", "k9 1111"]
skus = set(sku)
for x in isbn:
skus -= {i for i in skus if x in i}
print(skus)
{'k6 6666', 'k7 7777', 'k8 8888'}