1

だから私は次のようなタプルのリストを持っています:

[
    ('Worksheet',),
    ('1a', 'Calculated'),
    ('None', 'None', 'None', 'None', 'None'),
    ('1b', 'General'),
    ('1b', 'General', 'Basic'),
    ('1b', 'General', 'Basic', 'Data'),
    ('1b', 'General', 'Basic', 'Data', 'Line 1'),
    ('1b', 'General', 'Basic', 'Data', 'Line 2'),
    ('None', 'None', 'None', 'None', 'None'),
    ('1c', 'General'),
    ('1c', 'General', 'Basic'),
    ('1c', 'General', 'Basic', 'Data'),
    ('None', 'None', 'None', 'None', 'None'),
    ('2', 'Active'),
    ('2', 'Active', 'Passive'),
    ('None', 'None', 'None', 'None', 'None'),
    ...
]

各タプルの長さは 1 ~ 5 です。これで終わるには、リストを再帰的に削減する必要があります。

[
    ('Worksheet',),
    ('1a', 'Calculated'),
    ('None', 'None', 'None', 'None', 'None'),
    ('1b', 'General', 'Basic', 'Data', 'Line 1'),
    ('1b', 'General', 'Basic', 'Data', 'Line 2'),
    ('None', 'None', 'None', 'None', 'None'),
    ('1c', 'General', 'Basic', 'Data'),
    ('None', 'None', 'None', 'None', 'None'),
    ('2', 'Active', 'Passive'),
    ('None', 'None', 'None', 'None', 'None'),
    ...
]

基本的に、次の行が前の行のすべてに一致する場合 +1 は、同じ階層を持つタプルの最大長まで削除します。

したがって、私の例に見られるように、タプルの最初の項目である 3 行が1cあったため、最長に短縮されました。

4

3 に答える 3

1

最初の要素でタプルをグループ化します。を使用しますitertools.groupby()(operator.itemgetter()キーを簡単に作成するために .

次に、各グループを個別にフィルタリングします。

from itertools import groupby, chain
from operator import itemgetter

def filtered_group(group):
    group = list(group)
    maxlen = max(len(l) for l in group)
    return [l for l in group if len(l) == maxlen]

filtered = [filtered_group(g) for k, g in groupby(inputlist, key=itemgetter(0))]
output = list(chain.from_iterable(filtered))

デモ:

>>> from itertools import groupby, chain
>>> from operator import itemgetter
>>> from pprint import pprint
>>> def filtered_group(group):
...     group = list(group)
...     maxlen = max(len(l) for l in group)
...     return [l for l in group if len(l) == maxlen]
... 
>>> filtered = [filtered_group(g) for k, g in groupby(inputlist, key=itemgetter(0))]
>>> pprint(list(chain.from_iterable(filtered)))
[('Worksheet',),
 ('1a', 'Calculated'),
 ('None', 'None', 'None', 'None', 'None'),
 ('1b', 'General', 'Basic', 'Data', 'Line 1'),
 ('1b', 'General', 'Basic', 'Data', 'Line 2'),
 ('None', 'None', 'None', 'None', 'None'),
 ('1c', 'General', 'Basic', 'Data'),
 ('None', 'None', 'None', 'None', 'None'),
 ('2', 'Active', 'Passive'),
 ('None', 'None', 'None', 'None', 'None')]
于 2013-10-23T13:58:01.360 に答える
1
def is_subtuple(tup1, tup2):
    '''Return True if all the elements of tup1 are consecutively in tup2.'''
    if len(tup2) < len(tup1): return False
    try:
        offset = tup2.index(tup1[0])
    except ValueError:
        return False
    # This could be wrong if tup1[0] is in tup2, but doesn't start the subtuple.
    # You could solve this by recurring on the rest of tup2 if this is false, but
    # it doesn't apply to your input data.
    return tup1 == tup2[offset:offset+len(tup1)] 

次に、入力リストをフィルタリングするだけです(ここで名前を付けlます):

[t for i, t in enumerate(l) if not any(is_subtuple(t, t2) for t2 in l[i+1:])]

さて、このリスト内包表記は、サブタプルが含まれているタプルよりも前にあるように、入力リストが一貫して順序付けられていることを前提としていますO(n**2)。終わり。

于 2013-10-23T14:27:47.333 に答える