提一个关于列表内部遍历的初级问题,望慷慨相助

2015-12-17 10:34:11 +08:00
 niqzhao
无编程背景新手初学 python, 在 Codewars 上面做题,遇到一个题目要求:将传入的任意名字列表里面四个字母长的名字列表返回,我想的办法是这样的:
def friend(x):
for value in x:
if len(value) != 4:
x.remove(value)
return x

然而传入测试列表['Ryan', '123', 'CoolMan']时,结果是这样:

friend(['Ryan', '123', 'CoolMan'])
['Ryan', 'CoolMan']

'123'被删掉了,'Coolman'没按我想的被删掉,请问原因是什么?

P.S. 解决这个问题本身的办法已经知道了,比如把四个字长的值放到新列表里,用 filter()等,这里希望知道该错误背后的原理。另外这种初级问题提在这合适吗,有更合适的地方请指条明路,不胜感激。
2065 次点击
所在节点    Python
13 条回复
imn1
2015-12-17 10:42:44 +08:00
原则,遍历时尽量不要改变原列表
应该新建列表,符合的扔过去,遍历完元列表没用就删掉,内存回收
niqzhao
2015-12-17 10:45:12 +08:00
@imn1 感谢回复
jmc891205
2015-12-17 10:50:41 +08:00
你把'123'删掉之后,'CoolMan'挪到了第 2 个元素的位置,但是迭代器已经到了第 3 个元素, for 循环就退出了。

如 @imn1 所说,遍历时不要改变正在遍历的容器,否则遍地是坑。
imn1
2015-12-17 10:57:48 +08:00
呃,你问原理啊,没看清
没看过源代码,说不清
猜想跟 @jmc891205 说的,因为列表是可遍历对象,感觉像指针一样指示 index ,不妨用 enumerate()测试看看

PS:问原理的话,不算初级问题了,至少我这初级就不懂, 2333
baichi
2015-12-17 13:42:41 +08:00
http://www.pythontutor.com 楼主你可能会需要这个工具
gejigeji
2015-12-17 14:15:48 +08:00
你要是在 C++这么写就会编译不过
bramblex
2015-12-17 14:26:59 +08:00
def friend(x):
----return list(filter(lambda n: len(n)!=4, x))

就一行代码的事
zealot0630
2015-12-17 14:31:09 +08:00
[v for v in x if len(v) == 4]

PS: python 的 lambda 实在太难看了
niqzhao
2015-12-17 16:14:23 +08:00
@baichi 这工具简直是坑底照明灯
niqzhao
2015-12-17 16:15:57 +08:00
@bramblex @zealot0630 你们这太 6 了 学习了
bramblex
2015-12-17 18:10:54 +08:00
@zealot0630 那我这样玩呢?/w\

friend :: [String] -> [String]
friend xs = do
x <- xs
if length x /= 4
then return x
else mempty
zhangyi2099
2015-12-17 18:22:17 +08:00
@bramblex 这是 Haskell ?
bramblex
2015-12-17 18:26:00 +08:00
@zhangyi2099 对啊……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/244132

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX