2

彼は、最も Pythonic なソリューションを探す興味深い問題です。mappings のリストがあるとし{'id': id, 'url': url}ます。リスト内のいくつかidの が重複しているため、すべての重複を削除して新しいリストを作成したいと考えています。私は次の機能を思いついた:

def unique_mapping(map):
    d = {}
    for res in map:
        d[res['id']] = res['url']

    return [{'id': id, 'url': d[id]} for id in d]

かなり効率的だと思います。しかし、「よりPython的な」方法はありますか? それとももっと効率的な方法ですか?

4

3 に答える 3

4

例を少し書き直して、ジェネレーター式を使用して最初の辞書を作成し、別のマッピングを作成する必要をなくすことができます。古いものを再利用するだけです:

def unique_mapping(mappings):
    return dict((m['id'], m) for m in mappings).values()

これはワンライナーとして出てきましたが、それでもかなり読みやすいと思います。

元のソリューションと私のソリューションを使用するときは、次の 2 つの点に注意する必要があります。

  • アイテムは、元の順序と同じ順序で常に返されるとは限りません。
  • 後のエントリは、同じ ID を持つ以前のエントリを上書きします

差し支えなければ、上記の解決策をお勧めします。それ以外の場合、この関数は順序を保持し、最初に検出された ID を優先して扱います。

def unique_mapping(mappings):
    addedIds = set()
    for m in mappings:
        mId = m['id']
        if mId not in addedIds:
            addedIds.add(mId)
            yield m

list(unique_mappings(mappings))ジェネレーターではなくリストが必要な場合は、で呼び出す必要があるかもしれません。

于 2008-10-09T07:47:09.597 に答える
2

改善できる点がいくつかあります。

  • 2 つのループを実行しています。1 つは元の dict で、もう 1 つは結果の dict です。代わりに、1 つのステップで結果を構築できます。

  • リスト全体を事前に構築することを避けるために、ジェネレーターを使用するように変更できます。(必要に応じて list(unique_mapping(items)) を使用して完全なリストに変換します)

  • 重複をチェックするだけの場合は、値を保存する必要はありません。代わりにセットを使用できます。

  • 元の辞書を返すのではなく、要素ごとに辞書を再作成しています。これは実際に必要な場合があります (たとえば、それらを変更していて、オリジナルに触れたくない場合など)。そうでない場合は、既に作成されている辞書を使用する方が効率的です。

実装は次のとおりです。

def unique_mapping(items):
    s = set()
    for res in items:
        if res['id'] not in s:
            yield res
            s.add(res['id'])
于 2008-10-09T07:54:23.453 に答える
1

これはもっと簡単にできると思います。辞書は重複キーを許容しません。マッピングのリストをマッピングの辞書にします。これにより、重複が削除されます。

>>> someListOfDicts= [
    {'url': 'http://a', 'id': 'a'}, 
    {'url': 'http://b', 'id': 'b'}, 
    {'url': 'http://c', 'id': 'a'}]

>>> dict( [(x['id'],x) for x in someListOfDicts ] ).values()

[{'url': 'http://c', 'id': 'a'}, {'url': 'http://b', 'id': 'b'}]
于 2008-10-09T12:32:04.873 に答える