【问题标题】:Iterating through Dictionary backwards in Python在Python中向后遍历字典
【发布时间】:2014-10-05 07:11:16
【问题描述】:

我有一个很长的元素字典,我想删除所有只有一个元素的列表的字典条目。 例如

    wordDict={'aardvark':['animal','shell'], 'bat':['animal', 'wings'], 
              'computer':['technology'], 'donut':['food','sweet']}

我想删除“计算机”条目,因为其中的列表只有一个元素。我首先遍历 wordDict 并将字典中的每个条目放在单独的列表中,使其看起来像这样

    wordList=[['animal','shell'],['animal','wings'],['technology'],['food','sweet']]

然后向后遍历该列表,检查列表中每个元素的长度是否大于 1。向后因为向前会导致索引在我删除时发生变化。

所以在 wordList 中,['technology'] 被删除,这就是剩下的

    wordList=[['animal','shell'],['animal','wings'],['food','sweet']]

问题在于,随着 wordDict 变得非常大(100k+ 字),将 wordDict 放入列表然后遍历该列表需要很长时间,我想提高效率。

我正在考虑向后遍历字典,检查每个条目是否有多个单词,如果没有,则删除字典条目。最后,需要返回的是一个列表,而不是一个字典,所以索引最终无关紧要,我只是将它们用于排序目的。

有没有办法做到这一点?

【问题讨论】:

    标签: python python-3.x dictionary


    【解决方案1】:

    您可以删除不想要的元素并创建一个新字典,使用字典理解,就像这样

    >>> {word: items for word, items in wordDict.items() if len(items) > 1}
    {'aardvark': ['animal', 'shell'],
     'bat': ['animal', 'wings'],
     'donut': ['food', 'sweet']}
    

    您正在遍历wordDict 字典并检查items 的长度是否大于1。如果是,则将其包含在正在构建的新字典中,否则不要包含它。

    【讨论】:

      【解决方案2】:

      第一个选项是 thefourtheye 建议的尝试rebuild the dictionary,并让列表中包含多个元素的唯一元素:-

      new_dict = {key:value for key,value in d.iteritems() if len(value) > 1} 
      

      第二个选项是迭代字典并相应地删除项目,但它不会像第一个选项那么有效。

      【讨论】:

        【解决方案3】:

        如果你只需要最后的列表,你可以这样做:

        wordList = list(filter(lambda x: len(x) > 1, wordDict.values()))
        

        不需要创建临时字典...

        编辑:另一种选择(实际上比上面更清晰,更快)是

        wordList = list(value for value in wordDict.values() if len(value) > 1)
        

        奖励:如果您不想过滤 empty 值,您可以这样做:

        wordList = list(filter(bool, wordDict.values()))
        

        编辑:这里也是替代方案(有点奇怪,但是是对的):

        wordList = list(value for value in wordDict.values() if value)
        

        空列表(和字典等)的逻辑值为False。

        【讨论】:

          【解决方案4】:

          我认为跟踪长度 = 1 的元素会更快。当将元素插入长度 = 1 的字典或对长度为 1 的元素执行操作时,将该元素的键放在类似的列表中“单打”。然后,当您需要时,使用“单曲”中的键删除所有长度 = 1 的元素。它消除了遍历字典所有元素的需要。

          例如插入字典时:

          def insert(wordDict, key, element, singles):
              wordDict[key] = element
              if len(element) == 1:
                  singles.append(key)
          

          并且,在对可能改变其长度的元素进行操作时:

          def some_operation(key, element, singles):
              # Do something.
              if len(element) == 1:
                  singles.append(key)
          

          最后,当您想要删除所有长度为 1 的元素时:

          def delete_singles(wordDict, singles):
              for k in singles:
                  wordDict.pop(k)
          

          现在,只需使用这些函数进行所有插入和修改,然后使用 delete_single() 进行删除。我希望它工作得快!

          【讨论】:

            【解决方案5】:

            人们可以在迭代时修改列表的长度,因为可以通过向后迭代来明智地做到这一点。但正如您所注意到的,它也很慢 (O(nk),其中 k 是被选中的项目数。

            在迭代时可能不会更改字典的键,因为这可能会导致作为迭代基础的内部哈希数组的重建。相反,必须创建一个单独的键集合来迭代。

            wordDict={'aardvark':['animal','shell'], 'bat':['animal', 'wings'], 
                          'computer':['technology'], 'donut':['food','sweet']}
            
            for key in list(wordDict.keys()):
                if len(wordDict[key]) <= 1:
                    del wordDict[key]
            
            print(wordDict)
            

            打印

            {'aardvark': ['animal', 'shell'], 'bat': ['animal', 'wings'], 'donut': ['food', 'sweet']}
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-10-30
              • 2023-03-29
              • 2023-03-12
              • 1970-01-01
              • 1970-01-01
              • 2022-09-22
              相关资源
              最近更新 更多