0

私は2つの大きなリストを持っています。それぞれがリストで構成されています。

list_1 = [[1, "BMW", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "BMW", "Boston", "01Jan2013"],...]

list_2 = [[1, "Mercedes", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "Toyota", "Boston", "01Jan2013"],...]

内部リストには常に同じアイテムタイプがあります。

list_1次に、内部リストの項目1、項目3、および項目4を使用して、各内部を1つの内部と一致させlist_2ます。つまり、シリアル番号、都市の起源、および日付です。これらのキーは常にlist_2と同じです。の内部リストは、でlist_10または1つの一致のみを持つことができlist_2ます。

これを行うための最もPython的で最速の方法は何ですか?リストを辞書に変換する必要がありますか?

4

5 に答える 5

3

(コメントに従って)重複を含めることができないと仮定すると、リストのリストではなく、のに変換list_1できます。そうすれば、演算子を使用して、特定のアイテムがセットに含まれているかどうかを効率的に確認できます。settuplein

リストは変更可能であるため(したがってハッシュ可能ではないため)、リストの代わりにタプルを使用する必要があります。そのため、リストをに入れることはできませんset。を使用した場合も同じことが当てはまりますが、ユースケースにdictはaのset方が適しているようです(のキーとして何を使用するかは明確ではありませんdict)。

于 2013-01-26T21:45:31.580 に答える
2

速度の面では、おそらく辞書を利用したいと思うでしょう。どうやら、リストを繰り返す必要があるようです。もちろん、辞書はリストを反復処理するよりも高速であるため、リストの少なくとも1つを辞書にすることができます。(2つの別々のリストであなたと同じように200,000のエントリを使用して次のソリューションをテストし、完了までの平均速度は0.109999秒でした。リストはそのマークをはるかに超えていました。)リストを使用しようとすると、おそらくそれに近づくことはありません。またはタプル。ただし、エントリの順序でzipなどを使用できる場合を除きます。シリアル番号は一意のように見えるので、次のように機能します(1つのリストを繰り返し処理してから、項目1、3、および4 [位置0、2、および3]を辞書の値と比較します)。

list_1 = [[1, "BMW", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "BMW", "Boston", "01Jan2013"]]

list_2 = [[1, "Mercedes", "Boston", "01Jan2013"], [37, "Chevrolet", "Denver", "05Jan2013"],
[854, "Toyota", "Boston", "01Jan2013"]]


dict_2 = dict()

for elem in list_2:
    dict_2[elem[0]] = elem[1:]

for item in list_1:
    if dict_2[item[0]][1:] == item[2:]:    # Have to offset the index since dict list only has three elements
        print item


[1, 'BMW', 'Boston', '01Jan2013']
[37, 'Chevrolet', 'Denver', '05Jan2013']
[854, 'BMW', 'Boston', '01Jan2013']

2番目のリストを辞書に変換すると、結果を取得するために1つのリストを反復処理するだけで済みます。このソリューションは、list_1からの各一致のサブリスト全体を返します。これは必要と思われます。両方のリストから完全に一致するサブリストが必要な場合、これは機能します。

for item in list_1:
    if dict_2[item[0]][1:] == item[2:]:
        print item, [item[0]] + dict_2[item[0]]


[1, 'BMW', 'Boston', '01Jan2013'] [1, 'Mercedes', 'Boston', '01Jan2013']
[37, 'Chevrolet', 'Denver', '05Jan2013'] [37, 'Chevrolet', 'Denver', '05Jan2013']
[854, 'BMW', 'Boston', '01Jan2013'] [854, 'Toyota', 'Boston', '01Jan2013']
于 2013-01-26T21:33:18.000 に答える
1

@omzと同様の解決策は、リストを辞書に変換することです。dictキーはタプル(serial,city,date)(アイテム1、3、および4)になり、値はもう1つのフィールド'make'(アイテム2)になります。次に、それらを一致させるために、list_1(now )のキーを繰り返し処理して、 :dict_1の対応するメンバーを取得しようとします。dict_2

dict_1 = {(1, "Boston", "01Jan2013"):"BMW", (37, "Denver", "05Jan2013"):"Chevrolet", (854, "Boston", "01Jan2013"):"BMW",...}

dict_2 = {(1, "Boston", "01Jan2013"):"Mercedes", (37, "Denver", "05Jan2013"):"Chevrolet", (854, "Boston", "01Jan2013"):"Toyota",...}

for k in dict_1:
    match = dict_2.get (k, None)
    if match is not None:
        print "Match found:", match
    else:
        print "No match"

当然、一致するものを見つけたときに行うことは、私が書いたものではありませんが、一致するものを見つける方法を示すのに役立つはずです。

于 2013-01-26T22:00:56.863 に答える
1

比較するフィールドを指定するキー関数を定義できます。

def item_key(item):
    return tuple(item[i] for i in [0, 2, 3])

dictキーとして使用できるように、ハッシュ可能である必要があります。アイテムキーからアイテム自体へのマッピング、または異なるアイテムが同じキーを共有できる場合はアイテムのリストを作成できます。

key_to_item2 = dict((item_key(item), item) for item in list2)

これで、 list1の各項目をdictに対してテストできます。

for item1 in list1:
    item2 = key_to_item2.get(item_key(item1))
    if item2 is None:
        # no match found
    else:
        # item2 in list2 matches item1 in list1

このアプローチは、他のフィールドを使用して照合したり、複数の照合をサポートしたりするために簡単に調整できます。

于 2013-01-26T21:27:49.473 に答える
1

「最良の」解決策は、あなたが望むものによって異なります。速度に関する場合は、入力のサイズによっては辞書が最適な場合があります。

明快さと簡潔さについてであれば、リストにとどまり、次のことを行うのは非常にPython的だと思います。

result = []
for l1 in list1:
    result.append([l2 for l2 in list2
                   if l1[0] == l2[0] and l1[2] == l2[2] and l1[3] == l2[3]])
    assert(len(result[-1]) in [0,1])
于 2013-01-26T21:44:03.527 に答える