Python检查列表项是不是(不)包含任何其他列表项
Posted
技术标签:
【中文标题】Python检查列表项是不是(不)包含任何其他列表项【英文标题】:Python Check if list item does (not) contain any of other list itemsPython检查列表项是否(不)包含任何其他列表项 【发布时间】:2018-01-03 04:05:00 【问题描述】:如果列表元素包含“非法”字符,我想删除它。合法字符在多个列表中指定。它们是这样形成的,其中alpha
代表字母表(a-z + A-Z),digit
代表数字(0-9),punct
代表标点符号(有点)。
alpha = list(string.ascii_letters)
digit = list(string.digits)
punct = list(string.punctuation)
这样,如果某项未出现在这些列表之一中,我可以将其指定为非法字符。
之后我有一个包含元素的列表:
Input = ["Amuu2", "Q1BFt", "dUM€n", "o°8o1G", "mgF)`", "ZR°p", "Y9^^M", "W0PD7"]
我想过滤掉包含非法字符的元素。所以这是我想要得到的结果(不需要订购):
var = ["Amuu2", "Q1BFt", "mgF)`", "Y9^^M", "W0PD7"]
编辑:
我已经尝试过(以及它的所有变体):
for InItem in Input:
if any(AlItem in InItem for AlItem in alpha+digit+punct):
FilInput.append(InItem)
仅使用过滤后的元素创建一个新列表,但这里的问题是当包含至少一个合法字符时元素会被添加。例如:"ZR°p"
被添加,因为它包含一个 Z、R 和一个 p。
我也试过了:
for InItem in Input:
if not any(AlItem in InItem for AlItem in alpha+digit+punct):
但在那之后,我不知道如何删除该元素。 哦,还有一个小技巧,为了让它变得更加困难,如果它有点快就好了,因为它需要完成数百万次。但它需要先发挥作用。
【问题讨论】:
你尝试过哪些事情? 【参考方案1】:定义一组合法字符。然后应用列表推导。
>>> allowed = set(string.ascii_letters + string.digits + string.punctuation)
>>> inp = ["Amuu2", "Q1BFt", "dUM€n", "o°8o1G", "mgF)`", "ZR°p", "Y9^^M", "W0PD7"]
>>> [x for x in inp if all(c in allowed for c in x)]
['Amuu2', 'Q1BFt', 'mgF)`', 'Y9^^M', 'W0PD7']
【讨论】:
哇,它有效。但是你能解释一下它是如何工作的吗?我真的不明白所有这些 x 和 c。 @WernerSchoemaker 将x
重命名为 word
和 c
重命名为 character
。现在有意义吗?【参考方案2】:
您的代码
正如你所提到的,只要any
字符是正确的,你就会追加单词。您需要检查它们是否all
正确:
filtered_words = []
for word in words:
if all(char in alpha+digit+punct for char in word):
filtered_words.append(word)
print(filtered_words)
# ['Amuu2', 'Q1BFt', 'mgF)`', 'Y9^^M', 'W0PD7']
您还可以检查没有一个不正确的字符:
filtered_words = []
for word in words:
if not any(char not in alpha+digit+punct for char in word):
filtered_words.append(word)
print(filtered_words)
但它的可读性要差得多。
为了提高效率,您不应在每次迭代期间将列表与alpha+digit+punct
连接。在任何循环之前,您应该一劳永逸地执行此操作。从这些列表中创建一个集合也是一个好主意,因为当允许的字符很多时,char in set
比 char in list
快得多。
最后,您可以使用列表推导来避免 for 循环。如果你做这一切,你最终会得到@timgeb's solution :)
正则表达式替代
您可以从列表中创建一个正则表达式模式并查看哪些单词匹配:
# encoding: utf-8
import string
import re
alpha = list(string.ascii_letters)
digit = list(string.digits)
punct = list(string.punctuation)
words = ["Amuu2", "Q1BFt", "dUM€n", "o°8o1G", "mgF)`", "ZR°p", "Y9^^M", "W0PD7"]
allowed_pattern = re.compile(
'^[' +
''.join(
re.escape(char) for char in (
alpha +
digit +
punct)) +
']+$')
# ^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^_\`\\|\\~]+$
print([word for word in words if allowed_pattern.match(word)])
# ['Amuu2', 'Q1BFt', 'mgF)`', 'Y9^^M', 'W0PD7']
你也可以写:
print(list(filter(allowed_pattern.match, words)))
# ['Amuu2', 'Q1BFt', 'mgF)`', 'Y9^^M', 'W0PD7']
re.compile
可能比简单地初始化 set
需要更多时间,但过滤可能会更快。
【讨论】:
【参考方案3】:如果所有字符都符合您的条件,您可以使用列表推导并检查 all
:
>>> [element for element in Input if all(c in alpha + digit + punct for c in element)]
['Amuu2', 'Q1BFt', 'mgF)`', 'Y9^^M', 'W0PD7']
【讨论】:
为每个字符连接相同的列表效率不高。【参考方案4】:对于您的问题,这是一个“不是”有效的解决方案,但它对于学习如何循环列表、字符等可能很有趣。
# coding=utf-8
import string
# Aux var
result =[]
new_elem = ""
# lists with legal characters
alpha = list(string.ascii_letters)
digit = list(string.digits)
punct = list(string.punctuation)
# Input strings
Input = ["Amuu2", "Q1BFt", "dUM€n", "o°8o1G", "mgF)`", "ZR°p", "Y9^^M", "W0PD7"]
# Loop all elements of the list and each char of them
for elem in Input:
## check each char
for char in elem:
if char in alpha:
#print 'is ascii'
new_elem += char
elif char in digit:
#print 'is digit'
new_elem += char
elif char in punct:
#print 'is punct'
new_elem += char
else:
new_elem = ""
break
## Add to result list
if new_elem != "":
result.append(new_elem)
new_elem = ""
print result
【讨论】:
以上是关于Python检查列表项是不是(不)包含任何其他列表项的主要内容,如果未能解决你的问题,请参考以下文章