4

1 つのマスター リストからいくつかの新しいリストを作成しようとしています。これにより、新しいリストにはマスター リストの類似アイテムが含まれます。具体的には、バス路線のリストがあります。サンプル データ セットを次に示します。

[u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']

ほとんどのバス ルートには、インバウンド (IB) とアウトバウンド (OB) の項目があります (複数の IB と OB があるものもあれば、ルートが 1 つしかないものもあり、それらはループ ルートです)。最終的には、IB ルートと OB ルートをマッピング ソフトウェアでマージしたいと考えています (方法は既に知っています)。

IB か OB かに関係なく、最初の 5 文字がバス ルートを表すようにファイル名を最初に作成しました。したがって、最初の 5 文字に基づいて類似アイテムをグループ化できます。たとえば、私が書くとき:

for route in routes:
    print route[0:5]

私は得る:

>>> 
Bus04
Bus04
Bus15
Bus15

Bus04およびBus04に関連するファイルBus15Bus15新しいリストに「グループ化」するにはどうすればよいですか。

[u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line']別の[u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']リストとして?

私は、各アイテムをループして、それぞれの最初の 5 文字を見て、新しい 5 文字のアイテムごとに新しいリストを作成する (そしてそのアイテムを新しいリストに追加する) か、リストが既に存在し、それに類似したアイテムを追加しています。

これをコードで書くのに苦労しているので、どんな助けも大歓迎です!

4

4 に答える 4

6

私はこれに使用collections.defaultdictします:

import collections

L = [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']
d = collections.defaultdict(list)
for elem in L:
    d[elem.split('_')[0]].append(elem)
print(dict(d))

これにより、次が生成されます。

{u'Bus04': [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line'],
 u'Bus15': [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']}

これまでに提案された他のいくつかのソリューションとは異なり、これは入力リストにエントリが表示される順序に関係なく機能します。

于 2012-12-20T17:37:58.603 に答える
3

itertools.groupbyなどのカスタムキー機能と併用できますlambda x: x[0:5]

これは、静的リストを提供するデモです(つまり、ジェネレーターだけではありません):

>>> import itertools
>>> lst = [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line', u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']
>>> [(key, list(val)) for key, val in itertools.groupby(lst, lambda x: x[0:5])]
Out[9]:
[(u'Bus04', [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line']),
 (u'Bus15', [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line'])]
于 2012-12-20T17:37:43.980 に答える
2
import collections

lists = collections.defaultdict(list)
for item in masterlist:
    lists[item[:5]].append(item)
于 2012-12-20T17:37:50.720 に答える
1

これには、ラムダ キー関数で groupby を使用できます。

from itertools import groupby
results = groupby(data, key=lambda x: x[0:5])

>>> for item, values in results:
>>>     print item, list(values)
Bus04 [u'Bus04_00_00_IB_pts_Line', u'Bus04_00_00_OB_pts_Line']
Bus15 [u'Bus15_00_00_IB_pts_Line', u'Bus15_00_00_OB_pts_Line']

NPE が彼のソリューションで述べたように、元のリストはソートされたリストでなければなりません。

ただし、一度に 1 つのエントリのみを処理する必要がある場合、このソリューションはメモリ効率が非常に高くなります。ジェネレータは 1 つの値のみを生成し、次の値が使用できるようになるまで待機するためです。

于 2012-12-20T17:38:49.620 に答える