重构python中的字典列表

时间:2017-10-18 18:37:46

标签: python list dictionary

我有以下的dicts列表:

[
   {"taskid": 1, "type": "input", "name": "First_in"},
   {"taskid": 1, "type": "input", "name": "Second_in"},
   {"taskid": 1, "type": "input", "name": "Third_in"},
   {"taskid": 1, "type": "output", "name": "First_out"},
   {"taskid": 1, "type": "output", "name": "Second_out"},
   {"taskid": 1, "type": "output", "name": "Third_out"},
   {"taskid": 2, "type": "input", "name": "First_in"},
   {"taskid": 2, "type": "output", "name": "First_out"},
   {"taskid": 2, "type": "output", "name": "Second_out"},
...]

我需要对其进行重组以获得以下结果:

[
   {"taskid": 1, 
    "input": ["First_in", "Second_in", "Third_in"], 
    "output": ["First_out", "Second_out", "Third_out"]
   },
   {"taskid": 2, 
    "input": ["First_in"], 
    "output": ["First_out","Second_out"]
   },
...]

这是我的代码:

def squash_records(rec):
    squashed = []
    # get all taskids
    tasks = []
    for item in rec:
        tasks.append(item['taskid'])
    for task in tasks:
        current_task = {}
        current_task['taskid'] = task
        current_task['input'] = [row['name'] for row in rec if row['type'] == 'input' and row['taskid'] == task]
        current_task['output'] = [row['name'] for row in rec if row['type'] == 'output' and row['taskid'] == task]
        squashed.append(current_task)
    return squashed

如果此数组是生成器,那么实现它的最佳方法是什么?我的意思是 - 单个for ...循环?

提前谢谢!

2 个答案:

答案 0 :(得分:1)

为了好玩,我在单行上做了这个:

$rootScope.checkLogin = function(welcome){
    $http({
        method: "GET",
        url: 'api/check-login',
    })
    .then(function(response){
        if(response.data.success){
            $rootScope.user = response.data.data.user;
            if(welcome){
                return $rootScope.showToast("Hallo, " + response.data.data.user.user_name + "!"); 
            }
        }
    })
}

答案 1 :(得分:1)

这是一个O(n)解决方案:

In [5]: from collections import defaultdict

In [6]: grouper = defaultdict(lambda:defaultdict(list))

In [7]: for d in data:
    ...:     grouper[d['taskid']][d['type']].append(d['name'])
    ...:

In [8]: grouper
Out[8]:
defaultdict(<function __main__.<lambda>>,
            {1: defaultdict(list,
                         {'input': ['First_in', 'Second_in', 'Third_in'],
                          'output': ['First_out', 'Second_out', 'Third_out']}),
             2: defaultdict(list,
                         {'input': ['First_in'],
                          'output': ['First_out', 'Second_out']})})

坦率地说,我会停在这里,因为我认为这是一个更方便的数据结构,但如果你真的需要一个列表:

In [9]: [{'taskid':k, **v} for k, v in grouper.items()]
Out[9]:
[{'input': ['First_in', 'Second_in', 'Third_in'],
  'output': ['First_out', 'Second_out', 'Third_out'],
  'taskid': 1},
 {'input': ['First_in'], 'output': ['First_out', 'Second_out'], 'taskid': 2}]

此外,如果data不是列表而是单遍迭代器(例如生成器),这将起作用。

此外,** splat语法不适用于Python 2,因此请使用:

In [10]: [dict(taskid=k, **v) for k, v in grouper.items()]
Out[10]:
[{'input': ['First_in', 'Second_in', 'Third_in'],
  'output': ['First_out', 'Second_out', 'Third_out'],
  'taskid': 1},
 {'input': ['First_in'], 'output': ['First_out', 'Second_out'], 'taskid': 2}]