4

私はPythonが初めてで、Googleで解決できない問題に直面しています。wxPython と ObjectiveListView を使用して GUI を作成しました。GUI の中心には、データを X 行 (データはユーザーがロード) および 5 列で表示するリスト コントロールがあります。

ユーザーがリスト コントロールから複数のエントリを選択すると (CTRL または Shift キーを押しながらクリック)、ObjectiveListView モジュールは辞書のリストを表示します。辞書には、リスト コントロールの行のデータが含まれています。これはまさに私が欲しいものです。

返されるリストは次のようになります。

print MyList
[{'id':1023, 'type':'Purchase', 'date':'23.8.2008', 'sum':'-21,90', 'target':'Apple Store'}, {'id':1024, 'type':'Purchase', 'date':'24.8.2008', 'sum':'-21,90', 'target':'Apple Store'}, {'id':23, 'type':'Purchase', 'date':'2.8.2008', 'sum':'-21,90', 'target':'Apple Store'}]

すべての辞書は同じキーを持ちますが、値は変わります。「id」値は一意です。ここで問題が始まります。ユーザーが選択したすべてのアイテムの共通値を取得したい。上記のリストでは、'sum':'-21,90' および 'target':'Apple Store' になります。

リスト内の辞書を適切に比較する方法がわかりません。大きな問題の 1 つは、リストに含まれる dict の数がユーザーによって決定されるため、事前にわからないことです。

リスト内包表記の方がよいという漠然とした考えがありますが、n個のリストではなく、2つのリストをリスト内包表記で比較する方法しか知りません。どんな助けでも大歓迎です。

4

5 に答える 5

7

私の答えは、1つの違いを除いて、MatthewTrevorの答えと同じです。

>>> mysets = (set(x.items()) for x in MyList)
>>> reduce(set.intersection, mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])

ここではset.intersection、新しいラムダを作成する代わりに使用します。私の意見では、これは「reduceはsetintersection演算子を使用してこのリストを縮小している」と直感的に読み取れるため、より読みやすくなっています。set.intersection組み込みのC関数と同様に、これもはるかに高速です。

質問に完全に答えるために、リスト内包表記を使用して値を抽出できます。

>>> mysets = (set(x.items()) for x in MyList)
>>> result = reduce(set.intersection, mysets)
>>> values = [r[1] for r in result]
>>> values
['-21,90', 'Purchase', 'Apple Store']

これは私にとって1行になってしまいます。しかし、それは完全にあなた次第です:

>>> [r[1] for r in reduce(set.intersection, (set(x.items()) for x in myList))]
['-21,90', 'Purchase', 'Apple Store']
于 2008-11-24T17:22:57.657 に答える
7
>>> mysets = (set(x.items()) for x in MyList)
>>> reduce(lambda a,b: a.intersection(b), mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])

最初に、辞書のリストを反復可能なキーと値のペアのセットのシーケンスに変換するジェネレーターを作成しました。ここでリスト内包表記を使用できますが、この方法ではリスト全体がさらに別のリストに変換されるわけではないため、リストの大きさがわからない場合に役立ちます。

次に、reduce を使用して、各セット間の共通値を見つける関数を適用しました。それ自体がセットであるセット 1 とセット 2 の交点、次にそのセットとセット 3 の交点などを見つけます。

reduce は Python 3.0 の組み込みとして非推奨になったと思いますが、functools では引き続き使用できるはずです。

もちろん、reduce の mysets をジェネレーター式に置き換えることでワンライナーにすることもできますが、読みやすさの IMO が低下します。実際には、おそらくさらに一歩進んで、ラムダを独自の行に分割することもできます。

>>> mysets = (set(x.items()) for x in MyList)
>>> find_common = lambda a,b: a.intersection(b)
>>> reduce(find_common, mysets)
set([('sum', '-21,90'), ('type', 'Purchase'), ('target', 'Apple Store')])

最終結果を dict にする必要がある場合は、次のようにラップします。

>>> dict(reduce(find_common, mysets))
{'sum': '-21,90', 'type': 'Purchase', 'target': 'Apple Store'}

dict は、最後に返されるタプルのセットなど、キーと値のペアの任意の反復子を受け入れることができます。

于 2008-11-24T16:16:20.100 に答える
2

まず、2 つの辞書の共通部分を計算する関数が必要です。

def IntersectDicts( d1, d2 ) :
    return dict(filter(lambda (k,v) : k in d2 and d2[k] == v, d1.items()))

次に、それを使用して任意の数の辞書を処理できます。

result = reduce(IntersectDicts, MyList)
于 2008-11-24T16:50:20.467 に答える
1

共通セットのみを探しているので、最初の辞書のキーを他のすべての辞書のキーと比較できます。

common = {}
for k in MyList[0]:
    for i in xrange(1,len(MyList)):
        if MyList[0][k] != MyList[i][k]: continue
        common[k] = MyList[0][k]

>>> common
{'sum': '-21,90', 'type': 'Purchase', 'target': 'Apple Store'}
于 2008-11-24T20:49:36.770 に答える
0

申し訳ありませんが、'type':'Purchase' も一般的な値の 1 つです。質問を編集するにはログインする必要があります。

于 2008-11-24T16:13:34.957 に答える