【问题标题】:How to add index into a dict如何将索引添加到字典中
【发布时间】:2016-07-23 13:12:36
【问题描述】:

例如,给定:

['A', 'B', 'A', 'B']    

我想拥有:

{'A': [0, 2], 'B': [1, 3]}

我尝试了一个类似的循环;添加找到字符的位置的索引,然后将其替换为'',以便下次循环通过时,它会传递到下一个字符。

但是,由于其他原因,该循环不起作用,我不知道如何继续。

【问题讨论】:

    标签: python list dictionary indexing list-comprehension


    【解决方案1】:

    使用enumeratesetdefault

    example = ['a', 'b', 'a', 'b']
    mydict = {}
    for idx, item in enumerate(example):
         indexes = mydict.setdefault(item, [])
         indexes.append(idx)
    

    【讨论】:

    • ​​​​​​​​​​​你也可以from collections import defaultdict并使用mydict = defaultdict(list),然后你不需要自己运行mydict.setdefault(item, [])我认为会更 Pythonic。
    • 但是你必须导入它 :P 好点子 - 如果你想提交一个编辑使用那个或 setdefault 的例子,我会接受它。
    • ​​​​​​​​​​​​​​​嗯,那不是the correct usage of edit。所以我不会提交编辑。但无论如何,这里是the documentation of collections.defaultdict
    【解决方案2】:

    一个简单的字典理解应该可以解决问题:

    {key: [index for index, x in enumerate(my_list) if x == key] for key in my_list}
    

    一个简单的试验:

    >>>> my_list = ['A','B','A','B']
    >>>> {key: [index for index, x in enumerate(my_list) if x == key] for key in my_list}
    >>>> {'A': [0, 2], 'B': [1, 3]}
    

    工作原理

    List comprehensions 通常在 Python 中用作 for 循环的语法糖。而不是写

    my_list = []
    for item in range(10):
        my_list.append(item)
    

    列表推导本质上可以让您将这一系列语句压缩成一行:

    my_list = [item for item in range(10)]
    

    当您看到列表推导式时,您应该记住它只是原始三行语句的精简版本。它们实际上是相同的 - 这里提供的唯一好处是简洁。

    一个类似的相关物种是dictionary comprehension。它类似于列表推导式,只是它允许您同时指定 both 键和值。

    一个字典理解的例子:

    {k: None for k in ["Hello", "Adele"]}
    >>>> {"Hello": None, "Adele": None}
    

    在我提供的答案中,我只是使用了一个字典理解

    • my_list拉出keys
    • 为来自my_list 的每个key 分配一个索引列表作为对应值

    从句法上讲,它扩展为一个相当复杂的程序,如下所示:

    my_dict = {}
    for key in my_list:
        indices = []
        for index,value in enumerate(my_list):
             if value == key:
                  indices.append(index)
        my_dict[key] = indices
    

    这里,enumerate 是一个标准库函数,它返回一个元组列表。每个元组的第一个元素引用列表的索引,第二个元素引用列表中该索引处的值。

    观察:

     enumerate(['a','b','a','b'])
     >>>> [(0,'a'),(1,'b'),(2,'b'),(3,'b')]
    

    这就是enumerate 的力量。

    效率

    与往常一样,过早优化是万恶之源。确实,这种实现效率低下:它重复工作,并且在二次时间中运行。然而,重要的是询问您的特定任务是否可以。对于相对较小的列表,这已经足够了。

    您可以查看某些优化。 @wilinx 的方法效果很好。 cmets 中的@Rob 建议对set(my_list) 进行迭代,这样可以防止重复工作。

    【讨论】:

    • 理解重复工作。也许... for key in set(my_list)
    • 这对我来说是新的,你能告诉我它是如何工作的吗?
    • ​​​​​​​​​​​​​​​嗯...注意,由于这种方式会一次又一次地循环列表,我认为它会比@987654323慢@.
    • 优化不是问题,而且这种方式看起来相对简单得多。
    • @LtotheV:​​​​​​​​​​​​​​​其实这种方式比较复杂。因为这种方式调用enumerate(my_list)my_list的长度+1”次。但是willnx 的方式只需要调用enumerate(my_list) 一次。那是不同的。但是,是的,这种方式虽然是单行版本。但如果您的列表不大,我不建议使用这种方式。
    【解决方案3】:

    为什么不改用itertools 中的defaultdict

    >>> from collections import defaultdict
    >>> d = defaultdict(list)
    >>> 
    >>> for i,x in enumerate(l):
            d[x].append(i)
    
    
    >>> d
    defaultdict(<class 'list'>, {'A': [0, 2], 'B': [1, 3]})
    

    【讨论】:

    • 等一下...defaultdict不是collections吗?
    • OP 有没有提到不导入任何东西? defaultdict 是从标准库导入的很常见的东西
    【解决方案4】:

    您需要做的就是为您使用正确的DataType。检查此链接-python doc。祝你好运。希望这会有所帮助。

    来源:https://docs.python.org/2/library/collections.html#collections.OrderedDict

    >>> # regular unsorted dictionary
    >>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
    
    >>> # dictionary sorted by key
    >>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
    OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
    

    【讨论】:

    • 这甚至不是同一个问题。他试图将列表中值的索引存储在字典中,而不是根据值对键:值对进行排序
    • @DanGayle 我的错!要么我没有正确阅读,要么后来添加了进一步的解释。感谢您指出:)
    猜你喜欢
    • 1970-01-01
    • 2011-03-08
    • 2011-05-18
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多