Python 修改和排除数组中的某些元素

Python 修改和排除数组中的某些元素,python,list,Python,List,我有一个数组,其中包含几个带有公共前缀的元素,另一个数组包含要排除的元素列表,但没有前缀。我想从所有元素中删除前缀,并排除那些需要排除的元素。例如: fullList = ['foo-1', 'foo-2', 'foo-3', 'foo-4', 'foo-5'] exclude = ['2', '4', '6'] 因此,我希望完整列表只包含['1','3','5']。我可以很容易地做一个循环,但我宁愿做一个理解。目前,我分两步进行: fullList = [element.replace('f

我有一个数组,其中包含几个带有公共前缀的元素,另一个数组包含要排除的元素列表,但没有前缀。我想从所有元素中删除前缀,并排除那些需要排除的元素。例如:

fullList = ['foo-1', 'foo-2', 'foo-3', 'foo-4', 'foo-5']
exclude = ['2', '4', '6']
因此,我希望完整列表只包含['1','3','5']。我可以很容易地做一个循环,但我宁愿做一个理解。目前,我分两步进行:

fullList = [element.replace('foo-', '') for element in fullList]
fullList = [element for element in fullList if element not in exclude]

我想知道-有没有更好的方法,特别是我能一步完成吗?

一步完成,你可以这样做:

[f.replace('foo-', '') for f in fullList if all(ex not in f for ex in exclude)]
# ['1', '3', '5']
或者按照您的原始逻辑,您可以将第一个理解作为生成器嵌入到第二个理解中:

[f_trim for f_trim in (f.replace('foo-', '') for f in fullList) if f_trim not in exclude]
# ['1', '3', '5']
excludeSet = set(exclude)
trimList = (f.replace('foo-', '') for f in fullList)
[e for e in trimList if e not in excludeSet]
如果列表较大,请使用集合:

excludeSet = set(exclude)
[f_trim for f_trim in (f.replace('foo-', '') for f in fullList) if f_trim not in excludeSet]
如果您考虑性能,并且为了更好的可读性,可以保留两行,第一行作为生成器:

[f_trim for f_trim in (f.replace('foo-', '') for f in fullList) if f_trim not in exclude]
# ['1', '3', '5']
excludeSet = set(exclude)
trimList = (f.replace('foo-', '') for f in fullList)
[e for e in trimList if e not in excludeSet]
考虑这种方法,它只适用于foo-之后的一位数:

如果您现在尝试打印完整列表,您将获得:

['1', '3', '5']
请注意,对于字符串,s[-1]返回其最后一个字符,例如:“abc”[-1]产生“c”

也适用于foo-之后的多个数字的解决方案:


按照Xcoder先生的思路,我建议对最高速度进行额外优化:

# exclude = set(exclude)  # uncomment if the exclude list is big
fullList = [x[4:] for x in fullList if x[4:] not in exclude]
# ['1', '3', '5']

4指数来源于我们对foo-长度的预先了解。直接切片应该比函数调用和搜索与替换过程快得多。

Neat!缺点是它只适用于个位数。如果是一个更大的列表,我也会把exclude变成一个集合。@zwer修复。也用了不止一个数字:不幸的是,我在问题中给出的只是一个例子;实际上,我在公共前缀后面有一个完整的字符串,所以第一个解决方案是不可接受的。我想到了第二个解决方案,但是两次调用替换看起来不太好。“BotChev调用替换两次不会影响性能。”BuntCheV——这也是一个错误的解决方案,考虑完整列表= [ Foo-1’,'Foo3','Foo-5’,'Foo-7','Foo-11','Foo-13','Foo-17','Foo-19']和排除=['1','7']。您希望您的结果为['3','5','11','17','19'],但第一个示例仅给出['3','5']当它对每个完整列表元素上的每个排除元素进行完整字符串搜索时,1会匹配其中包含1的每个元素。事实上,so ex not in f应该替换为更严格的not f.endswithex。@bontchev-然后你会遇到一个公共结尾的问题,使用与上面相同的设置,你会得到['3',5',13',19']因为11以1结尾,17以7结尾。为了避免冲突,比较必须以另一种方式进行,即检查排除列表中的剩余部分。如果您想使用Psidom的解决方案,请使用他的第二种方法,这样做。如果您对性能感兴趣,完整列表中有1M个元素,排除列表中有1M个元素总的来说,在我的系统上,Psidom的2解决方案需要~0.42秒,Xcoder先生的~0.46秒,我的~0.21秒。很高兴有人了解我:
# exclude = set(exclude)  # uncomment if the exclude list is big
fullList = [x[4:] for x in fullList if x[4:] not in exclude]
# ['1', '3', '5']