2012-06-15 118 views
2

我想遍历列表检查列表中的每个字符串的字符。python检查列表中的字符串?

test = [str(i) for i in range(100)] 

for i in test: 
    if '0' or '4' or '6' or '8' in str(i): 
     test.remove(i) 

我想这将是很好,但是,该列表是在此之后:

[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99] 

凡“2”被删除,但,在“41”是不是?我注意到它唯一的偶数,但不知道为什么。

回答

5

你有两个问题。首先,总是采用这个if声明。

if '0' or '4' or '6' or '8' in str(i): 

由于字符串0是一个非零长度的字符串,并且因此True040,因此True。声明的其余部分无关紧要。

我希望你真的想测试一下是否每个都是整数的字符串表示形式。正如你现在写的那样,你只是测试8是否在字符串中,而且甚至没有经过测试,因为表达式在它到达之前评估为True。像这样的东西会工作:

if any(x in i for x in '0468'): 

顺便说一句,str(i)是多余的,因为你的清单已经是一个字符串列表。

另一个问题是,您正在从正在迭代的列表中删除项目。所以,这里是发生了什么:

  • 的第一个项目,0,被删除的,因为你的if语句总是服用。
  • 第二项1成为第一项,因为您删除了0
  • for循环继续执行第二项,现在为2

换句话说,因为您删除0,1从不测试。因此,每个其他项目(所有偶数)都被删除。

避免这种情况在你的代码最简单的方法是遍历列表的副本:

for i in test[:]: 
11

您的代码有两个问题。首先是您在迭代时修改列表。第二个问题是您以错误的方式使用or运算符 - if语句中的条件始终为True

这里有一个固定的版本:

test = [i for i in range(100) if set("0468").isdisjoint(str(i))] 
0

的问题是在这里与线:

if '0' or '4' or '6' or '8' in str(i): 

这是不正确。最好是这样写:

if any(x in i for x in '0468'): 

第二个问题(如上所述的Sven)是在迭代它的同时修改列表。

最好的解决办法是:

[i for i in test if not any(x in i for x in '0468')] 
+0

你还在修改'test'在遍历它。 –

+0

你是对的,我只是试图接近这个问题。我会修复我的答案 –

+0

谢谢,但即使你愿意,这也会是公平的:) –

0
itms = ['0','4','6','8'] 
test = [str(i) for i in range(100) if not any([x in str(i) for x in itms])] 

也许这就是....未经检验的,但我认为它会工作

2

考虑一下:

(Pdb) i=2 
(Pdb) i='2' 
(Pdb) '0' or 'beer' in str(i) 
'0' 
(Pdb) bool('0') 
True 

你明白为什么'0' or '4' or '6' or '8' in str(i)并不总是一个布尔值?

现在,考虑你删除的内容:

>>> l=[str(i) for i in range(10)] 
>>> for i in l: 
... print i 
... print l 
... l.remove(i) 
... 
0 
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] 
2 
['1', '2', '3', '4', '5', '6', '7', '8', '9'] 
4 
['1', '3', '4', '5', '6', '7', '8', '9'] 
6 
['1', '3', '5', '6', '7', '8', '9'] 
8 
['1', '3', '5', '7', '8', '9'] 

当你删除就地元素,而你遍历列表中,你缩短了列表,并跳过每下一个值。

Sven has the right pythonic solution,但我觉得更长的解释可能是值得的。

1

当您执行类似'0' or '4'的操作时,or操作员将验证第一个参数('0')是否为false-ish,如果不是false,则返回第一个值。由于'0'是不是假的(它是一个非空字符串,如布尔使用时产生True),它将返回的第一个值和下面的一个甚至不会考虑:如果您重复它

>>> '0' or '4' 
'0' 

,你会得到相同的结果:

>>> '0' or '4' or '6' or '8' 
'0' 

此外,in运营商具有更大的优先级,所以它会每次or前执行:

在 '88' '0' 或 '4' 或 '6' 或 '8' '0'

你想在你的病情做的是验证任何值是结果:

>>> '0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i) 
True 
>>> i = 17 
>>> '0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i) 
False 

这还不是最完美的解决方案,但它是你的意图的最好的翻译。

那么,什么是优雅的解决方案?作为sugested通过@sven,您可以创建寻求字符的集合(more about it):

>>> sought = set("0468") 
>>> sought 
set(['0', '8', '4', '6']) 

,然后创建了一套在你的电话号码位数:

>>> i = 16 
>>> set(str(i)) 
set(['1', '6']) 

现在,只是看看they are disjoint

>>> i = 16 
>>> sought.isdisjoint(set(str(i))) 
False 
>>> i = 17 
>>> sought.isdisjoint(set(str(i))) 
True 

在这种情况下,如果设定是脱节,那么要保留它:

>>> found = [] 
>>> for i in range(100): 
...  if sought.isdisjoint(set(str(i))): 
...   found.append(i) 
... 
>>> found 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 

大多数时候,每次你让自己创造一个for环路滤波迭代器的时候,你真正需要的是一个list comprehension

>>> [i for i in range(100) if sought.isdisjoint(set(str(i)))] 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 

或者,用笨拙,但更多的新手友好构建:

>>> [i for i in range(100) if not ('0' in str(i) or '4' in str(i) or '6' in str(i) or '8' in str(i))] 
[1, 2, 3, 5, 7, 9, 11, 12, 13, 15, 17, 19, 21, 22, 23, 25, 27, 29, 31, 32, 33, 35, 37, 39, 51, 52, 53, 55, 57, 59, 71, 72, 73, 75, 77, 79, 91, 92, 93, 95, 97, 99] 
相关问题