2

itertools.dropwhile3番目の要素の後にあるジェネレーターからのみ要素を返す ために使用しようとしていますが、少し問題があります。

from itertools import dropwhile

    it = (i for i in range(10,20))
    a = dropwhile(enumerate < 3, it)   
    next(a)
    TypeError: 'bool' object is not callable 

私が探している出力は次のとおりです。

[14, 15, 16, 17, 18, 19]

誰かが私のコードの何が悪いのかを説明し、実用的な解決策を提供できますか?ありがとう。

4

5 に答える 5

8

itertoolsあなたが望むことなどを正確に行う機能を提供します。Python標準ライブラリから、

itertools。islice反復可能[、開始]、停止[、ステップ])

イテレータから選択した要素を返すイテレータを作成します。startがゼロ以外の場合、iterableの要素はstartに到達するまでスキップされますその後、ステップが1より高く設定されてアイテムがスキップされない限り、要素は連続して返されます。stopが、の場合None、イテレータが使い果たされるまで反復が続行されます。それ以外の場合は、指定された位置で停止します。

>>> import itertools
>>> it = (i for i in range(10, 20)) # it = xrange(10, 20)
>>> a = itertools.islice(it, 4, None)
>>> list(a)
[14, 15, 16, 17, 18, 19]
于 2012-08-22T21:51:21.870 に答える
3

predicatetoの引数itertools.dropwhileは、単一の引数を受け入れる関数である必要があり、enumerate < 3単なるステートメントです。Python 2.xでは、これは常にFalseと評価されます。"type" > "int"これは、Python 3.xでは、結果が。になるためTypeError: unorderable types: type() < int()です。

コードを変更して引き続き使用する方法は次のdropwhileとおりです。

>>> it = (i for i in range(10, 20))
>>> a = dropwhile(lambda i_v: i_v[0] < 4, enumerate(it))
>>> list(a)
[(4, 14), (5, 15), (6, 16), (7, 17), (8, 18), (9, 19)]

enumerateインデックスを使用して現在の値を削除するかどうかを決定するラムダを作成できるように、iterableで呼び出す必要があることに注意してください。ただし、これは、結果が(index, value)単なる値ではなくタプルのリストになることを意味します。また、の4番目の要素である、< 4から始めたいので、比較をに変更しました。14it

より良い代替案はitertools.isliceDeokhwanの答えのように使用することです。

于 2012-08-22T21:56:14.317 に答える
1

ここにある他の回答のいくつかは役に立ちますが、要求された結果を正確に提供するわけではありません。受け入れられた答えは有用性を説明していますitertools.islice()が、使用itertools.dropwhile()が要件である場合、それは完全には正しくありません。他のいくつかの答えは不必要に複雑です。

単純な解決策は、予想よりも見つけやすいかもしれません。例えば:

list(dropwhile(lambda x: x < 14, xrange(10, 20)))

list()要求された特定の結果がだったので、これをラップしました[14, 15, 16, 17, 18, 19]。その部分を削除しdropwhile()て、などでイテレータとして使用できます.next()。これはイテレータであるため、私が使用したのではなく、イテレータrange()を使用xrange()した方が効率的であるためです。 range()動作しますが、おそらくそれほど効率的ではありません。

enumerate()目標の一部が同様に使用することであったかどうかはわかりません。たぶんそうだったかもしれませんが、この例enumerateでは関数ではなく変数として使用されています。要求された結果を取得するために列挙は必要ありません。また、それは質問の一部ではなかったので、誤って使用されたと思います。

他の人が指摘したように、質問の例では、範囲からすべてのアイテムを取得するために理解を使用する必要はありませんでした。この答えもそれを使用していません。コードをさらに単純化する場合、要求された結果を取得するための最も簡単なソリューションは次のとおりです。

range(14, 20)

ただし、これにはを使用するという目標は含まれていませんitertools.dropwhile()

于 2016-07-29T22:06:41.240 に答える
-1

それを試してください:

a = dropwhile(lambda x:x < 3, it)  

引数は呼び出し可能でなければなりません。

于 2012-08-22T21:50:45.517 に答える
-1
 it = (i for i in range(10,20))

これはちょっと冗長です、なぜ単にrange(10,20)(またはxrange)を使用しないのですか?

dropwhile引数として関数を期待し、ブール値を提供しているため、コードが壊れています(関数enumerateを数値3と比較して作成されていますが、これは少し奇妙です!)

enumerateを使用するソリューションは、次のようになります。

a = dropwhile(lambda (i,val): i<3), enumerate(seq))

ただし、aそれでも列挙されたペア(インデックス、値)のリストです。

より効率的な方法は、おそらく次のようになります。

class Counter:
    def __init__(self):
        self.n = 0

    def __call__(self):
        current = self.n
        self.n += 1
        return current

ここで実際に動作しているのを見てください、それは非常に簡単です)

次に、次のように使用できます。

c = Counter()
a = dropwhile(lambda elem: c() < 3, seq)

これにより、を使用して目標を達成できますdropwhile。カウンターインスタンスは、seqの要素ごとに1回呼び出され、毎回次の番号を返します。


そうは言っても、あなたは:を使用する方がはるかに良いですitertools.islice

import itertools
a = itertools.islice(range(10, 20), 3, None)

isliceリストスライスとよく似myList[3:]たスライス(この場合は要素#3から最後まで)を実行できますが、引数として任意のシーケンスを取ることができます。

于 2012-08-22T22:01:33.313 に答える