【问题标题】:Python: Sort a list into multiple lists or dictionaryPython:将列表排序为多个列表或字典
【发布时间】:2012-09-15 01:36:38
【问题描述】:

我有一个字符串列表,这是一个例子:

wallList = ['wall_l0', 'wall_l1', 'wall_broken_l0', 'wall_broken_l1',
             'wall_vwh_l0','wall_vwh_l1', 'wall_vwh_broken_l0', 
             'wall_vwh_broken_l1', 'wall_vpi_l0', 'wall_vpi_l1', 
             'wall_vpi_broken_l0', 'wall_vpi_broken_l1']

我想按墙壁类型和状态(默认/损坏)将它们组合在一起:

[['wall_l0', 'wall_l1'],['wall_broken_l0', 'wall_broken_l1']]

[['wall_vwh_l0', 'wall_vwh_l1'],['wall_vwh_broken_l0', 'wall_vwh_broken_l1']] 

[['wall_vpi_l0', 'wall_vpi_l1'],['wall_vpi_broken_l0', 'wall_vpi_broken_l1']]

有人知道如何最好地做到这一点,或者知道 python 食谱吗?

【问题讨论】:

    标签: python list sorting dictionary


    【解决方案1】:

    这里有一个简单的方法:

    import itertools, re
    results = [list(v) for (k, v) in itertools.groupby(sorted(wallList),
            lambda x: re.sub(r'\d+', '0', x))]
    

    这不会保留顺序,但它会为您提供所需的相同输出。

    它的工作原理是查看所有数字都转换为“0”的版本并对重复项进行分组。

    【讨论】:

      【解决方案2】:

      编辑:显然我的回答只是部分正确,因为我忘了按“状态”进行组织。正确答案来自@samy.vilar。

      使用itertools.groupby:

      >>> from itertools import groupby
      >>> [list(g) for k,g in groupby(sorted(wallList), lambda r: r[:-1])]
      [['wall_broken_l0', 'wall_broken_l1'], ['wall_l0', 'wall_l1'], ['wall_vpi_broken_l0
      ', 'wall_vpi_broken_l1'], ['wall_vpi_l0', 'wall_vpi_l1'], ['wall_vwh_broken_l0', 'w
      all_vwh_broken_l1'], ['wall_vwh_l0', 'wall_vwh_l1']]
      

      【讨论】:

        【解决方案3】:

        有趣的是,首先我们需要按墙类型将其分解,这样我们才能做到这一点。

        >>> from itertools import groupby
        >>> wallList = ['wall_l0', 'wall_l1', 'wall_broken_l0', 'wall_broken_l1',
                 'wall_vwh_l0','wall_vwh_l1', 'wall_vwh_broken_l0', 
                 'wall_vwh_broken_l1', 'wall_vpi_l0', 'wall_vpi_l1', 
                 'wall_vpi_broken_l0', 'wall_vpi_broken_l1']
        >>> list(groupby(sorted(wallList), lambda wall: wall.replace('_broken', '')[:-3]))
        [('wall', <itertools._grouper object at 0x1004edc50>), ('wall_vpi', <itertools._grouper object at 0x1004edb90>), ('wall_vwh', <itertools._grouper object at 0x1004eda90>)]
        

        太好了,现在我们有了让那些被损坏的类型分开的类型。

        这就是所有东西放在一起的样子。

        >>> from itertools import groupby
        >>> wallList = ['wall_l0', 'wall_l1', 'wall_broken_l0', 'wall_broken_l1',
                 'wall_vwh_l0','wall_vwh_l1', 'wall_vwh_broken_l0', 
                 'wall_vwh_broken_l1', 'wall_vpi_l0', 'wall_vpi_l1', 
                 'wall_vpi_broken_l0', 'wall_vpi_broken_l1']
        
        >>> values = [[list(v) for k, v in groupby(values, lambda value: '_broken_' in value)] 
        ...             for key, values in groupby(sorted(wallList), lambda wall: wall.replace('_broken', '')[:-3])]
        >>> from pprint import pprint
        >>> pprint(values)
        [[['wall_broken_l0', 'wall_broken_l1'], ['wall_l0', 'wall_l1']],
         [['wall_vpi_broken_l0', 'wall_vpi_broken_l1'],
          ['wall_vpi_l0', 'wall_vpi_l1']],
         [['wall_vwh_broken_l0', 'wall_vwh_broken_l1'],
          ['wall_vwh_l0', 'wall_vwh_l1']]]
        

        当然还有其他方法,但这似乎很简洁。

        这是另一种方式:

        >>> from collections import defaultdict
        >>> values = defaultdict(lambda : defaultdict(list))
        >>> for wall in wallList:
        ...     if 'broken' in wall:
        ...         values[wall[:-3].replace('_broken', '')]['broken'].append(wall)
        ...     else:
        ...         values[wall[:-3]]['default'].append(wall)
        ... 
        >>> values.items()
        [('wall', defaultdict(<type 'list'>, {'default': ['wall_l0', 'wall_l1'], 'broken': ['wall_broken_l0', 'wall_broken_l1']})), ('wall_vpi', defaultdict(<type 'list'>, {'default': ['wall_vpi_l0', 'wall_vpi_l1'], 'broken': ['wall_vpi_broken_l0', 'wall_vpi_broken_l1']})), ('wall_vwh', defaultdict(<type 'list'>, {'default': ['wall_vwh_l0', 'wall_vwh_l1'], 'broken': ['wall_vwh_broken_l0', 'wall_vwh_broken_l1']}))]
        >>>
        

        第二种方法应该更快,因为我们只迭代一次,字典查找是恒定的,我们可以通过名称和状态访问任何一组墙...

        >>> values['wall']['default']
        ['wall_l0', 'wall_l1']
        >>> values['wall_vpi']['default']
        ['wall_vpi_l0', 'wall_vpi_l1']
        >>> values['wall_vpi']['broken']
        ['wall_vpi_broken_l0', 'wall_vpi_broken_l1']
        >>>
        

        【讨论】:

        • 啊,对了,我忘了它也需要按状态组织。这实际上是正确的答案。 +1
        【解决方案4】:

        在_上拆分:string.split('_')。如果你得到 2 个字段,你就有了退化的情况。如果得到 3,则按 3 的中间字段分组。列表字典可能会有所帮助,或者更好的是 collections.defaultdict(list)。

        【讨论】:

        • 这并不能真正回答问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-04
        • 2021-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-30
        • 1970-01-01
        相关资源
        最近更新 更多