2009-02-28 12 views
50

データ要素を保持するだけのCスタイルの構造体に似たように動作する単純なクラスを作成しているとしましょう。私は特定の値と等しい属性を持つオブジェクトのオブジェクトのリストを検索する方法を理解しようとしています。以下は私がしようとしていることを説明するための簡単な例です。例えばPythonでオブジェクトのリストを検索する

class Data: 
    pass 

myList = [] 

for i in range(20): 
    data = Data() 
    data.n = i 
    data.n_squared = i * i 
    myList.append(data) 

どのように私はそれがn == 5を持つ要素が含まれているかどうかを判断するためにはmyListのリストを検索するに行きますか?

私はグーグルでPythonドキュメントを検索していましたが、リストの理解でこれを行うことができると思いますが、わかりません。私はPython 2.4.3を使用しなければならないと付け加えるかもしれないので、新しいgee-whiz 2.6や3.xの機能は私には利用できません。

+0

あなたの例のおそらく意図的でない癖:。に相当します。ます。myList = [データ()のn == 0、データ()は、n = 1 、...] data.nはrange()によって代入され、data.nはmyListのインデックスになります。したがって、myListをインデックス値で参照するだけで、任意のData()インスタンスをプルアップできます。もちろん、後でmyList [0] .n = 5.2などを変更することができます。そしてこの例はおそらく過度に単純化されていました。 – DevPlayer

答えて

66

あなたはリスト内包とすべてマッチング要素のリストを取得することができます:あなたの場合は

[x for x in myList if x.n == 30] # list of all elements with .n==30 

をリストにのいずれかの要素が含まれていて、それが(比較的)効率的に一致しているかどうかを確認したい場合は、

def contains(list, filter): 
    for x in list: 
     if filter(x): 
      return True 
    return False 

if contains(myList, lambda x: x.n == 3) # True if any element has .n==3 
    # do stuff 
+19

、またはmyList内のxの任意の(custom_filter(x)(x.n == 30の場合))が含まれています。 – nosklo

+0

noskloの構文エラー - ジェネレータの周りに余分なセット()が必要です。 – gahooa

+0

そうではありません。それを試してみてください。 –

1

あなたはそれらの値が等しい場合、それはあまりにも、その後、__dict__属性が等しい(同じプロパティ)あるかどうかを確認し、可能性があり、あなたのDataクラスに__eq____hash__メソッドを追加する必要があります。あなたはそれをした場合testmyListである場合

、あなたは

test = Data() 
test.n = 5 

found = test in myList 

inキーワードチェックを使用することができます。

あなただけが使用できるData中のAA nプロパティにしたい場合:

class Data(object): 
    __slots__ = ['n'] 
    def __init__(self, n): 
     self.n = n 
    def __eq__(self, other): 
     if not isinstance(other, Data): 
      return False 
     if self.n != other.n: 
      return False 
     return True 
    def __hash__(self): 
     return self.n 

    myList = [ Data(1), Data(2), Data(3) ] 
    Data(2) in myList #==> True 
    Data(5) in myList #==> False 
25
[x for x in myList if x.n == 30]    # list of all matches 
any(x.n == 30 for x in myList)     # if there is any matches 
[i for i,x in enumerate(myList) if x.n == 30] # indices of all matches 

def first(iterable, default=None): 
    for item in iterable: 
    return item 
    return default 

first(x for x in myList if x.n == 30)   # the first match, if any 
+0

おそらく最も一般的な使用例である「最初の」方法のため、これは良い答えです。 – galarant

36

だけで完全なものにするため、のが最も簡単なおそらくでした仕事を忘れないようにしましょう:

for i in list: 
    if i.n == 5: 
    # do something with it 
    print "YAY! Found one!" 
24
filter(lambda x: x.n == 5, myList) 
+23

Pythonを学びたい人にとって、ラムダを理解することは基本的なことです。 – vartec

+1

まあ、はい、いいえ - リストの解説とoperator.attrgetterのような主要な関数のメーカーをソートすると、 'lambda'sはほとんど使用されません。 –

7

あなたは、コレクション内の項目を探すためにinを使用することができ、かつあなたが興味のある分野を抽出するためのリストの理解。これは、リスト、セット、タプル、および__contains__または__getitem__を定義するものすべてに適用されます。

if 5 in [data.n for data in myList]: 
    print "Found it" 

も参照してください:

46

、シンプルでエレガント、そしてパワフル:

組み込みと接続詞でジェネレータ式...(パイロット反復可能なのいずれかの要素が真であれば真

任意の(反復可能)-> 戻る:本町2.5+)

any(x for x in mylist if x.n == 10) 

は、次のように定義されたPythonのany()組み込みを使用しています。

def any(iterable): 
    for element in iterable: 
     if element: 
      return True 
    return False 
+0

ニース。あなたはいくつかの括弧(== not =)を保存するために任意の(x.n == 10の場合はxをmylistのxにする)ことができます。 –

3

辞書の使用を検討してください:

myDict = {} 

for i in range(20): 
    myDict[i] = i * i 

print(5 in myDict) 
+0

Or: d = dict((i、i * i)in i(範囲(20))) – hughdbrown

+0

私は自分の質問を説明するのに使った小さな問題を解決しますが、根本的な問題は本当に解決しませんでした。私が探していた答え(5年以上前)は、リストの理解度でした。 :) – m0j0

関連する問題