0

各反復でループの上限を更新するにはどうすればよいですか? 次のコードでは、各ループで List が短縮されます。ただし、lenList をグローバルとして定義したにもかかわらず、for、in ループの 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)
4

5 に答える 5

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 (私は信じています) では、省略可能なパラメーターを渡して enumerate の開始値を制御することもできますidx

于 2012-12-05T04:27:50.370 に答える
1

ここでの問題range()は、ループの開始時に一度だけ評価され、その時点で範囲ジェネレーター (または 2.x のリスト) が生成されることです。その後、範囲を変更することはできません。その数値と不変は言うまでもなく、新しい値を に割り当てていますが、それlenListはその使用には影響しません。

最善の解決策は、この動作に依存しないようにアルゴリズムの動作を変更することです。

于 2012-12-05T04:27:42.930 に答える
0

この問題は、関数の動作を少し変更するだけで非常に簡単になります。既存のリストから類似のアイテムを削除する代わりに、それらのアイテムを省略して新しいアイテムを作成して返します。

最初の項目との類似点を削除するという特定のケースでは、これによりかなり単純化され、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)は、コードを追跡しにくくする可能性があるため、どちらも避ける価値のある方法であることに注意してください。

于 2012-12-05T05:14:44.563 に答える
0

range、ループの最初の繰り返しの前に構築されるオブジェクトであるため、そのオブジェクトの値を繰り返し処理しています。代わりに while ループを使用する必要がありますが、Lattyware と gddc が指摘しているように、あまり Pythonic ではありません。

于 2012-12-05T04:29:06.273 に答える
0

上記のコードで効果的にループしているのは、最初の反復自体で生成されたリストです。

上記を次のように書くこともできます

li = range(1,lenList)
for i in li:
    ... your code ...

li の作成後に lenList を変更しても、li には影響しません

于 2012-12-05T04:29:31.920 に答える