1

リストのリストがあります。最初の 3 つの要素が共通のサブリストがある場合は、それらを 1 つのリストにマージし、4 番目の要素をすべて追加します。

この問題は、コードと必要な出力で最もよく説明されています。

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

# output:
# [['apple', 50, 60, 19], ['orange', 70, 50, 8]]

私はすでに同様の問題のコードを持っています (しばらく前にスタック オーバーフローの別のユーザーから提供されました) が、それを完全には理解していないため、それに応じて変更することはできません。このコードは、0 番目と 2 番目の要素が同じかどうかをチェックし、同じ場合はサブリストをマージし、1 番目と 3 番目の要素を追加します。

import defaultdict
data = [['42x120x1800', 50, '50x90x800', 60],
        ['42x120x1800', 8, '50x90x800', 10],
        ['2x10x800', 5, '5x9x80', 6]]

d = defaultdict(lambda :[0, 0])
for sub_list in data:
    key = (sub_list[0], sub_list[2])
    d[key][0] += sub_list[1]
    d[key][1] += sub_list[3]

new_data = [[key[0], val[0], key[1], val[1]] for key, val in d.iteritems()]
# [['2x10x800', 5, '5x9x80', 6], ['42x120x1800', 58, '50x90x800', 70]]

新しい問題に適合するようにコードをどのように変更する必要がありますか? 時間をかけてコードも徹底的に説明していただければ幸いです。

4

3 に答える 3

3

int最初の 3 つの要素をキーとして使用し、デフォルト値のファクトリとして使用することで、同じ原則を使用できますdefaultdict(したがって0、初期値として取得します)。

from collections import defaultdict

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

d = defaultdict(int)
for sub_list in a_list:
    key = tuple(sub_list[:3])
    d[key] += sub_list[-1]

new_data = [list(k) + [v] for k, v in d.iteritems()]

Python 3 を使用している場合は、次のように簡略化できます。

d = defaultdict(int)
for *key, v in a_list:
    d[tuple(key)] += v

new_data = [list(k) + [v] for k, v in d.items()]

スター付きのターゲットを使用してリストからすべての「残りの」値を取得できるため、各サブリストはほとんどが に割り当てられkey、最後の値は に割り当てられv、ループが少し単純になります (そして.iteritems()、dict にはメソッドがありません).items()すでにイテレータであるため、Python 3 )。

したがって、デフォルト値として をdefaultdict使用0し、最初の 3 つの値から生成されたキーごとに (辞書キーとして使用できるようにタプルとして) 最後の値を合計します。

  • したがって、最初の項目['apple', 50, 60, 7]で key を作成し、('apple', 50, 60)それを検索してd(存在しない場所で、新しい値を作成するためにdefaultdict使用します)、その最初の項目から を追加します。int()07

  • ('orange', 70, 50)key と valueについても同じことを行います8

  • 3 番目の項目では、キーを再度取得し、既存のに('apple', 50, 60)追加します。合計19個。127d[('apple', 50, 60)]

次に、(キー、値) のペアをリストに戻して完了です。これにより、次の結果が得られます。

>>> new_data
[['apple', 50, 60, 19], ['orange', 70, 50, 8]]

データの並べ替えを必要とする別の実装では、次を使用しますitertools.groupby

from itertools import groupby
from operator import itemgetter

a_list = [['apple', 50, 60, 7],
          ['orange', 70, 50, 8],
          ['apple', 50, 60, 12]]

newlist = [list(key) + [sum(i[-1] for i in sublists)] 
    for key, sublists in groupby(sorted(a_list), key=itemgetter(0, 1, 2))]

同じ出力に対して。データがソートされていない場合、これは遅くなりますが、さまざまなアプローチを知っておくとよいでしょう。

于 2013-01-23T21:05:28.223 に答える
1

私はこのようなことをします:

>>> a_list = [['apple', 50, 60, 7],
...           ['orange', 70, 50, 8],
...           ['apple', 50, 60, 12]]
>>> 
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> from operator import itemgetter
>>> getter = itemgetter(0,1,2)
>>> for lst in a_list:
...     d[getter(lst)].extend(lst[3:])
... 
>>> d
defaultdict(<type 'list'>, {('apple', 50, 60): [7, 12], ('orange', 70, 50): [8]})
>>> print [list(k)+v for k,v in d.items()]
[['apple', 50, 60, 7, 12], ['orange', 70, 50, 8]]

しかし、これは合計を与えません。次のようにして簡単に修正できます。

print [list(k)+[sum(v)] for k,v in d.items()]

Martijn によるもう少し洗練されたソリューションよりもこれを好む理由はあまりありませんが、ユーザーが 4 つ以上の項目を含む入力リストを使用できるようになることを除けば (後者の要素は期待どおりに合計されます)。言い換えれば、これはリストを渡します:

a_list = [['apple', 50, 60, 7, 12],
          ['orange', 70, 50, 8]]

同じように。

于 2013-01-23T21:05:10.567 に答える
0

[:3]最初の 3 つの要素を取得できるようにキーを形成します。

于 2013-01-23T21:03:46.980 に答える