我正在尝试遍历列表,检查列表中每个字符串的字符串。
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”不是?我注意到它只有偶数,但不知道为什么。
答案 0 :(得分:11)
您的代码存在两个问题。第一个是你在迭代它时修改列表。第二个是您以错误的方式使用or
运算符 - if
语句中的条件始终为True
。
这是一个固定版本:
test = [i for i in range(100) if set("0468").isdisjoint(str(i))]
答案 1 :(得分:5)
你有两个问题。首先,始终使用if
语句。
if '0' or '4' or '6' or '8' in str(i):
因为字符串0
是一个非零长度的字符串,因此是True
。 0
或4
为0
,因此为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[:]:
答案 2 :(得分: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,但我觉得更长的解释可能是值得的。
答案 3 :(得分: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'中的'p''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
这不是最优雅的解决方案,但它是您意图的最佳翻译。
那么,什么是优雅的解决方案?由@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]
答案 4 :(得分: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')]
答案 5 :(得分: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])]
也许......那是未经测试的,但我认为它会起作用