【问题标题】:list to dictionary conversion with multiple values per key?每个键有多个值的列表到字典转换?
【发布时间】:2011-07-19 16:36:26
【问题描述】:

我有一个包含键/值对的 Python 列表:

l = [[1, 'A'], [1, 'B'], [2, 'C']]

我想将列表转换为字典,其中每个键的多个值将聚合成一个元组:

{1: ('A', 'B'), 2: ('C',)}

迭代解法很简单:

l = [[1, 'A'], [1, 'B'], [2, 'C']]
d = {}
for pair in l:
    if pair[0] in d:
        d[pair[0]] = d[pair[0]] + tuple(pair[1])
    else:
        d[pair[0]] = tuple(pair[1])

print(d)

{1: ('A', 'B'), 2: ('C',)}

对于这项任务,是否有更优雅的 Pythonic 解决方案?

【问题讨论】:

    标签: python list dictionary type-conversion


    【解决方案1】:
    from collections import defaultdict
    
    d1 = defaultdict(list)
    
    for k, v in l:
        d1[k].append(v)
    
    d = dict((k, tuple(v)) for k, v in d1.items())
    

    d 现在包含 {1: ('A', 'B'), 2: ('C',)}

    d1 是一个以列表为值的临时默认字典,将在最后一行转换为元组。这样,您将追加到列表,而不是在主循环中重新创建元组。

    【讨论】:

      【解决方案2】:

      使用列表而不是元组作为字典值:

      l = [[1, 'A'], [1, 'B'], [2, 'C']]
      d = {}
      for key, val in l:
          d.setdefault(key, []).append(val)
      
      print(d)
      

      使用普通字典通常比 defaultdict 更可取,特别是如果您只构建一次,然后在以后的代码中继续读取它:

      首先,普通字典的构建和访问速度更快。

      其次,更重要的是,如果您尝试访问一个不存在的密钥,而不是静默创建该密钥,那么后面的读取操作将出错。普通字典可让您明确说明何时要创建键值对,而 defaultdict 始终在任何类型的访问中隐式创建它们。

      【讨论】:

      • 使用d.setdefault(key,[]).append(val)d.get(key,[]).append(val)有什么区别/优势?
      • setdefault() 的优点是使用 .get() 不起作用:\
      • @jtlz2 .get() 仅从字典中检索值。如果给定键没有条目,get 将愉快地返回新列表并允许将值附加到该列表,但不会更新字典以实际包含新列表,因此新列表将在之后被垃圾回收追加新值。
      【解决方案3】:

      这种方法比较高效,也比较紧凑:

      reduce(lambda x, (k,v): x[k].append(v) or x, l, defaultdict(list))
      

      在 Python3 中,这变为(明确导出):

      dict(functools.reduce(lambda x, d: x[d[0]].append(d[1]) or x, l, collections.defaultdict(list)))
      

      请注意,reduce 已移至 functools,并且 lambda 不再接受元组。此版本在 2.6 和 2.7 中仍然有效。

      【讨论】:

      • 不错,但在 python 3.5 或更高版本中无效
      【解决方案4】:

      输入列表中的键是否已经排序?如果是这种情况,您就有了一个实用的解决方案:

      import itertools
      
      lst = [(1, 'A'), (1, 'B'), (2, 'C')]
      dct = dict((key, tuple(v for (k, v) in pairs)) 
                 for (key, pairs) in itertools.groupby(lst, lambda pair: pair[0]))
      print dct
      # {1: ('A', 'B'), 2: ('C',)}
      

      【讨论】:

      • 如果你import operator,你可以写itertools.groupby(sorted(lst), operator.itemgetter(0))
      【解决方案5】:

      我创建了一个值列表,如下所示:

      performance_data = driver.execute_script('return window.performance.getEntries()')  
      

      然后我必须将数据(名称和持续时间)存储在具有多个值的字典中:

      dictionary = {}
          for performance_data in range(3):
              driver.get(self.base_url)
              performance_data = driver.execute_script('return window.performance.getEntries()')
              for result in performance_data:
                  key=result['name']
                  val=result['duration']
                  dictionary.setdefault(key, []).append(val)
              print(dictionary)
      

      【讨论】:

        【解决方案6】:

        我的数据在 Pandas.DataFrame 中

        myDict = dict()
        
        for idin set(data['id'].values):
            temp = data[data['id'] == id]
            myDict[id] = temp['IP_addr'].to_list()
            
        myDict
        

        给我一​​个包含键、ID、映射到 >= 1 IP_addr 的字典。第一个 IP_addr 是 Guaranteed。即使temp['IP_addr'].to_list() == []

        ,我的代码也应该可以工作
        {'fooboo_NaN': ['1.1.1.1', '8.8.8.8']}
        

        【讨论】:

          猜你喜欢
          • 2019-05-05
          • 1970-01-01
          • 2020-10-15
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多