5

それを理解するために、Pythonで座標ペアのリストを反復処理し、座標の1つが負であるすべてのケースを削除しようとしています。例えば:

配列内:

map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]

いずれかの座標が < 0 であるすべてのペアを削除して、次のようにします。

map = [[2, 3], [7, 1]]

私の問題は、python リストにギャップができないことです。そのため、次のようにループすると:

i = 0
for pair in map:
        for coord in pair:
            if coord < 0:
                del map[i]
    i += 1

要素が削除されるとすべてのインデックスがシフトし、反復が台無しになり、あらゆる種類の問題が発生します。悪い要素のインデックスを別のリストに保存してから、それらの要素をループして削除しようとしましたが、同じ問題があります.1つがなくなると、リスト全体がシフトし、インデックスが正確ではなくなります.

足りないものはありますか?

ありがとう。

4

8 に答える 8

3

これにはリスト内包表記を使用できます。

>>> mymap = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
>>> mymap = [m for m in mymap if m[0] > 0 and m[1] > 0]
>>> mymap
[[2, 3], [7, 1]]
于 2011-08-23T15:21:05.943 に答える
3

リストが大きくない場合、最も簡単な方法は新しいリストを作成することです:

In [7]: old_map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]

In [8]: new_map=[[x,y] for x,y in a_map if not (x<0 or y<0)]

In [9]: new_map
Out[9]: [[2, 3], [7, 1]]

old_map = new_map他のペアを破棄したい場合は、これをフォローアップできます。

リストが非常に大きい場合、同等のサイズの新しいリストを作成するのが問題になる場合は、リストから要素をその場で削除できます-トリックは、最初に末尾から要素を削除することです:

the_map = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
for i in range(len(the_map)-1,-1,-1):
    pair=the_map[i]
    for coord in pair:
        if coord < 0:
            del the_map[i]

print(the_map)

収量

[[2, 3], [7, 1]]

PS。mapは非常に便利な組み込みの Python 関数です。mapこれは組み込みをオーバーライドするため、変数に名前を付けないことをお勧めします。

于 2011-08-23T15:23:18.127 に答える
1

リストへの参照が他にない場合はmap、リスト内包表記が最適です。

map = [[a,b] for (a,b) in map if a > 0 and b > 0]

他の参照があり、 によって参照されるリストから要素を実際に削除するmap必要がある場合は、 のコピーを反復処理する必要がありますmap

for coord in map[:]:
    if coord[0] < 0 or coord[1] < 0:
        map.remove(coord)
于 2011-08-23T15:27:55.877 に答える
0

リストが十分に小さい場合は、他の回答で詳しく説明されているように、必要な要素だけを含むコピーを作成する方が効率的です。

ただし、リストが大きすぎる場合、または何らかの理由でリスト オブジェクトから要素を削除する必要がある場合は次の小さなヘルパー関数が非常に便利であることがわかりました。

def filter_in_place(func, target, invert=False):
    "remove all elements of target where func(elem) is false"
    pos = len(target)-1
    while pos >= 0:
        if (not func(target[pos])) ^ invert:
            del target[pos]
        pos -= 1

あなたの例では、これは次のように適用できます。

 >>> data = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
 >>> def is_good(elem):
         return elem[0] >= 0 and elem[1] >= 0
 >>> filter_in_place(is_good, data)
 >>> data
 [[2, 3], [7, 1]]

(これは filter_in_place の単なるリスト指向バージョンであり、すべての基本 Python データ型をサポートするものはもう少し複雑です)。

于 2011-08-24T01:30:13.790 に答える
0

個人的には、インプレース変更を好みます。

li = [[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]]
print li,'\n'


N = len(li)
for i,(a,b) in enumerate(li[::-1], start=1):
    if a<0 or b<0:
        del li[N-i]
print li

->

[[-1, 2], [5, -3], [2, 3], [1, -1], [7, 1]] 

[[2, 3], [7, 1]]
于 2011-08-23T16:25:21.373 に答える
0

新しいリストを作成せずにこれをその場で実行したい場合は、len(map)-1 から 0 まで実行するインデックスで for ループを使用するだけです。

for index in range(len(map)-1,-1,-1):
    if hasNegativeCoord(map[index]):
        del(map[index])

あまりPythonicではないことは認めます。

于 2011-08-23T15:31:16.593 に答える
0

itertools.ifilter()/ifilterfalse()まさにこれを行うために存在します:述語によってイテラブルをフィルタリングします(明らかにインプレースではありません)。さらに良いことに、フィルタリングされたリスト オブジェクト全体を作成して割り当てることは、可能な限り避けて、単に反復処理を行います。

import itertools

l = [(4,-5), (-8,2), (-2,-3), (4,7)]

# Option 1: create a new filtered list
l_filtered = list( itertools.ifilter(lambda p: p[0]>0 and p[1]>0, l) )

# Option 2:
for p in itertools.ifilter(lambda p: p[0]>0 and p[1]>0, l):
    ... <subsequent code on your filtered list> 
于 2013-11-12T00:03:52.897 に答える
-2

del pairおそらく代わりに欲しいでしょう。

于 2011-08-23T17:15:38.447 に答える