【问题标题】:Creating dictionary from list in Python - dict key omits Identical items in the list在 Python 中从列表创建字典 - 字典键省略列表中的相同项目
【发布时间】:2018-02-05 16:38:07
【问题描述】:

从列表创建字典时,字典的键会忽略列表中的相同项,并将最后一项存储为键。

例如:

lst1 = [["Apple",20.00,"Swiss"],
    ["Banana",5.00,"Brazil"],
    ["Strawberry",25.00,"Swiss"],
    ["Pear",12.00,"Greece"],
    ["Mango",3.00,"Peru"],
    ["Avacado",7.00,"Peru"]]

my_dict = {val[2]:val[:2] for val in lst1}

print (my_dict)

打印这个

{'Swiss': ['Strawberry', 25.0], 'Brazil': ['Banana', 5.0], 'Greece': ['Pear', 12.0], 'Peru': ['Avacado', 7.0]}

据我了解,这样做是因为键不能相同,那么为什么不将相同键的值分组到一个列表中。像这样

{
    'Swiss': [["Apple",20.00],['Strawberry', 25.0]],
    'Brazil': ['Banana', 5.0],
    'Greece': ['Pear', 12.0],
    'Peru': [["Mango",3.00],['Avacado', 7.0]]
}

有什么方法可以在纯 Python 中做到这一点?

【问题讨论】:

    标签: python python-3.x list dictionary


    【解决方案1】:

    您不能对此使用字典推导,因为它不知道前面的键已经存在。

    您必须使用直接循环。将所有值添加到列表中,而不仅仅是重复的值。不要在这里混合结构,这只会在以后造成更多的麻烦。如果你不这样做,你将不得不检测你是否有一个嵌套列表或一个包含一个水果和价格的平面列表。

    您可以使用普通字典:

    my_dict = {}
    for fruit, price, origin in lst1:
        my_dict.setdefault(origin, []).append([fruit, price])
    

    如果缺少键(第一个参数),dict.setdefault() 调用会在字典中添加一个空列表。然后它返回给定键的值(可能是已经存在的列表或新的空列表)。然后该线路调用list.append() 添加水果和价格。

    或者您可以在缺少键时使用collections.defaultdict() object 创建空列表:

    from collections import defaultdict
    
    my_dict = defaultdict(list)
    for fruit, price, origin in lst1:
        my_dict[origin].append([fruit, price])
    

    使用defaultdict 的代码更简洁一些,但缺点是该对象现在将继续为丢失的键生成空列表,即使由于代码中的错误您可能不打算这样做。

    两者都产生了预期的结果:

    >>> my_dict = {}
    >>> for fruit, price, origin in lst1:
    ...     my_dict.setdefault(origin, []).append([fruit, price])
    ...
    >>> my_dict
    {'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
    >>> from collections import defaultdict
    >>> my_dict = defaultdict(list)
    >>> for fruit, price, origin in lst1:
    ...     my_dict[origin].append([fruit, price])
    ...
    >>> my_dict
    defaultdict(<class 'list'>, {'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]})
    

    【讨论】:

      【解决方案2】:

      这类“累积”问题不能简单地用列表推导式(或影响可读性的丑陋副作用)来解决。

      您希望collections.defaultdict(list) 创建一个情侣列表作为值,国家作为键:

      lst1 = [["Apple",20.00,"Swiss"],
          ["Banana",5.00,"Brazil"],
          ["Strawberry",25.00,"Swiss"],
          ["Pear",12.00,"Greece"],
          ["Mango",3.00,"Peru"],
          ["Avacado",7.00,"Peru"]]
      
      result = collections.defaultdict(list)
      
      for fruit,price,country in lst1:
          result[country].append([fruit,price])
      
      print(dict(result))  # convert to dict for a cleaner representation when printing
      

      结果:

      {'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]], 'Brazil': [['Banana', 5.0]], 'Greece': [['Pear', 12.0]], 'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
      

      【讨论】:

        【解决方案3】:

        据我所知,这不能在comprehension 中完成,但您可以使用setdefaultlst1 中每个列表的每个第二个元素设置为key 中的dictionary然后您可以立即append 将其切片(正如您所做的那样)。 setdefault 的简洁之处在于,如果 key 已经存在,我们可以追加到它,或者创建 key,如果不存在则然后追加。这两个操作都是在没有if-statement 的情况下完成的。

        d = {}
        for l in lst1:
            d.setdefault(l[2], []).append(l[:2])
        

        给予:

        {'Brazil': [['Banana', 5.0]],
         'Greece': [['Pear', 12.0]],
         'Swiss': [['Apple', 20.0], ['Strawberry', 25.0]],
         'Peru': [['Mango', 3.0], ['Avacado', 7.0]]}
        

        【讨论】:

        • @MartijnPieters 我的错!我只是模仿了问题中使用的切片。奇怪的是,使用 [:1] 切片(就像 OP 所做的那样)并没有产生他们声称的输出:/
        • 他们刚刚纠正了他们的问题,因为我正要在评论中指出这一点。 :-)
        • @JoeIddon 抱歉,粘贴时没有注意到。
        • @Raja 没问题,请记住为未来的访客接受某人的回答
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-05
        • 2021-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多