是否有更多pythonic方法在列表中组合重复的对象?

时间:2013-10-12 01:36:50

标签: python

我有一个对象列表。每个对象都是一个唯一的实例,由名称和值的任意组合组成。我想将具有重复名称的对象组合到同一个类的新实例中,其值是所有重复项的值的列表。这是我的非pythonic方法:

def normalise_repeatable_options(options):
    flat = {}
    for o in options:
        if isinstance(o, Option):
            flat.setdefault(o.long, []).append(o)

    # Ensure options stay in the order they were prescribed.
    parsed = []
    for o in options:
        if isinstance(o, Option):
            dups = flat.get(o.long)
            if dups:
                parsed.append(Option.combine(*tuple(dups)))
                del flat[o.long]
        else:
            parsed.append(o)

    return parsed

更新:函数的输入和预期输出

input = [
    Option('-f', '--filter', 1, 'merge file'),
    Option('-f', '--filter', 1, 'merge anotherfile'),
    Argument(None, 'a'),
    Argument(None, 'b'),
    Argument(None, 'c')
]

output = [
    Option('-f', '--filter', 1, ['merge file', 'merge anotherfile']),
    Argument(None, 'a'),
    Argument(None, 'b'),
    Argument(None, 'c')
]

我还包含了Object.combine类方法,以防万一你想知道它是做什么的:

@classmethod
def combine(class_, *opts):
    t = opts[0]
    if len(opts) == 1: return t
    return class_(t.short, t.long, t.argcount, [o.value for o in opts])

3 个答案:

答案 0 :(得分:1)

无法测试,关于这样的事情?

def normalise_repeatable_options(options):
    parsed = []
    flat = defaultdict(list)

    for o in options:
        if isinstance(o, Option):
            # For the first instance of this object, add a placemarker
            if o.long not in flat:
                parsed.append(o.long)

            flat[o.long].append(o)
        else:
            parsed.append(o)

    return [Option.combine(*tuple(flat[o])) if isinstance(o, str) else o for o in parsed]

这样,您可以构建parsed列表,为要替换的Option对象留下placemarkers。我假设输入列表中没有任何对象属于str类型。

答案 1 :(得分:1)

你可以从这里开始:

from collections import defaultdict

def normalise_repeatable_options(options):
    actual_options = [o for o in options if isinstance(o, Option)]
    non_options = [o for o in options if not isinstance(o, Option)]

    flat = defaultdict(list)
    for o in actual_options:
        flat[o.long].append(o)

    parsed = (
        # Make list of the non-options plus ...
        non_options +

        # a flattened lists of Options plus ...
        [Option.combine(*tuple(dups)) for dup in flat.values() if len(dup) > 1] +

        # a list of Options
        [value[0] for value in flat.values() if len(value) == 1]
    )
    return parsed

答案 2 :(得分:0)

尝试列表理解:)

不确定这是否适用于您的情况,因为我根据一个代码到另一个代码的简单映射修改了代码。

你通过check isinstance得到了单位,所以你不必再检查一下。

此代码中可能存在小错误:

def normalise_repeatable_options(options):
    flat = {}
    parsed = []
    [flat.setdefault(o.long, []).append(o) if isinstance(o, Option)
     else parsed.append(o) for o in options]

    [parsed.append(Option.combine(*tuple(lst))) if len(lst) > 1 
     else parsed.append(lst) for lst in flat.values()]

    return parsed