如何在每次迭代中更新循环的上限?在以下代码中,List在每个循环中缩短。但是,for循环中的lenList不是,即使我将lenList定义为全局。任何想法如何解决这个问题? (我使用的是Python 2.sthg) 谢谢!
def similarity(List):
import difflib
lenList = len(List)
for i in range(1,lenList):
import numpy as np
global lenList
a = List[i]
idx = [difflib.SequenceMatcher(None, a, x).ratio() for x in List]
z = idx > .9
del List[z]
lenList = len(List)
X = ['jim','jimmy','luke','john','jake','matt','steve','tj','pat','chad','don']
similarity(X)
答案 0 :(得分:2)
在python中循环索引是不好的做法。你可能能够完成你想要的东西(编辑评论):
def similarity(alist):
position = 0
while position < len(alist):
item = alist[position]
position += 1
# code here that modifies alist
如果列表中有任何条目,则会评估True
,如果列表为空,则列出False
。通过这种方式,您可以使用在操作其项目期间可能增长的列表。
此外,如果您绝对必须拥有索引,您也可以获得这些索引:
for idx, item in enumerate(alist):
# code here, where items are actual list entries, and
# idx is the 0-based index of the item in the list.
在...... 3.x(我相信)你甚至可以传递一个可选参数来枚举以控制idx
的起始值。
答案 1 :(得分:1)
这里的问题是range()
仅在循环开始时评估一次,并在那时生成范围生成器(或2.x中的列表)。然后你不能改变范围。更不用说数字和不可变数,因此您要为lenList
分配一个新值,但这不会影响它的任何用途。
最佳解决方案是更改算法的工作方式,而不是依赖此行为。
答案 2 :(得分:0)
range
是在循环的第一次迭代之前构造的对象,因此您将迭代该对象中的值。你需要使用while循环,虽然Lattyware和g.d.d.c指出,它不会是非常Pythonic。
答案 3 :(得分:0)
您在上面的代码中有效循环的是在第一次迭代中生成的列表。
您可以将以上内容写成
li = range(1,lenList)
for i in li:
... your code ...
创建li后更改lenList对li
没有影响答案 4 :(得分:0)
通过对函数的工作方式进行一些小修改,这个问题将变得非常容易:不是从现有列表中删除类似的项目,而是创建并返回一个省略这些项目的新项目。
对于仅删除 first 项目的相似性的特定情况,这简化了相当多的时间,并且无需涉及Numpy的花哨索引(您实际上并未使用它,因为对np.array
}的遗失呼叫:
import difflib
def similarity(lst):
a = lst[0]
return [a] + \
[x for x in lst[1:] if difflib.SequenceMatcher(None, a, x).ratio() > .9]
从这个基础上,可以递归地为列表中的每个项重复它 - 你需要将列表理解在最后传递回similarity
,并处理接收空列表:
def similarity(lst):
if not lst:
return []
a = lst[0]
return [a] + similarity(
[x for x in lst[1:] if difflib.SequenceMatcher(None, a, x).ratio() > .9])
另请注意,在函数内部导入并命名变量list
(隐藏内置list
)都是值得避免的做法,因为它们会使您的代码更难以遵循。