【问题标题】:Python iterating through dictionaryPython遍历字典
【发布时间】:2020-12-05 03:01:04
【问题描述】:

我正在尝试遍历字典,但我不确定在循环时如何更新。

我正在尝试做的事情(Simulating LFU cache): 请求被接受, 逐个遍历每个请求,并统计每个使用字典的频率。

如果字典包含超过 8 个键,则删除频率最低的值,如果值的频率都相等,则删除字典中的 LOWEST 键。

因此删除当前 8 中最低的键并将第 9 键放入其中。

然后继续这样做,直到剩下 8 个值。

目前我有这个:

    requests=[1, 13, 15, 1, 3, 4, 2, 12, 10, 4, 1, 15, 15, 11, 14, 7, 10, 9, 14, 5]
    lst=[] #only holds 8 ints
    def leastFrequent():
        #user inputs requests manually
            print (requests)
            freq = {} #Dictionary
        
            for i in requests:
                if i in freq.keys():
                    #Increase frequency by 1
                    freq[i] += 1
                    print("Hit", i)
                else:
                    #If not set frequency to 1
                    freq[i] = 1
                    print("Miss", i)
            #I want to move my while loop inside this i think?? but i get errors with it being a dictionary

           freq = sorted(freq.items(), key=lambda k: k[0])#places dictionary into list of lists
           freq.sort(key=lambda x: x[1])#sort in order
           print("Converted frequency:",str(freq))
        
            while len(freq)>8:
                print("Size greater than 8..\n",str(freq[0]))
                del freq[0]#atm this just deletes the first value printed since it should be the lowest
                if len(freq)<=8:
                    break
        #i then move elements[0] into a final list to be printed
            lst=[item[0] for item in freq] 
            print ("\nPrinting final list")        
            print(lst)
            
    leastFrequent()

这样做的问题是它在逐个迭代时不会删除,它首先计算所有术语然后删除最低的术语。

这会导致错误的输出:

 [11, 12, 13, 4, 10, 14, 1, 15]

预期输出:

[1, 13, 15, 4, 12, 11, 14, 5]

顺序无关紧要,我想尝试不使用任何库。

对不起,如果我对编程很陌生并且我正在尝试学习如何使用字典和列表,这听起来很令人困惑。

【问题讨论】:

    标签: python


    【解决方案1】:

    也许我在你的描述中遗漏了一些东西,但按照你的逻辑,我得到了相同的输出。

    我相信您的代码是错误的,在计数后循环 - 但也许在这种情况下它奇怪地不会改变输出。

    requests=[1, 13, 15, 1, 3, 4, 2, 12, 10, 4, 1, 15, 15, 11, 14, 7, 10, 9, 14, 5]
    
    freq = {}
    
    for r in requests:
        r = str(r)
        if r in freq:
            freq[r]+=1
            print(f'Hit {r}')
        else:
            freq[r]=1
            print(f'Miss {r}')
        if len(freq.keys()) > 8:
            # Get list of keys that share the lowest frequency
            k = [int(k) for k, v in freq.items() if v == min(freq.values())]
            print(f'Requests sharing the lowest frequency of {min(freq.values())} -> {k}')
            print(f'Dropping lowest request value -> {min(k)}')
            del freq[str(min(k))]
            
    print([int(x) for x in freq.keys()])
    

    最终输出

    [1, 13, 15, 4, 12, 10, 11, 14]
    

    【讨论】:

    • 感谢您的帮助,我尝试继续进行,但非常感谢您
    【解决方案2】:

    您的解释非常令人困惑,但据我了解,我们有键值对和变量的收入,它们保存为字典(散列图),如果频率具有相同的值,您希望保持最高频率或最高(键) .简而言之,您只想在每次更新字典时重新创建字典。让我们来看看你的代码:

    # creates dictionary out of frequencies based on the input list
    def simulating_list(req, req_list):
        req_list[req] = 1 if req not in req_list else req_list[req]+1
    
    # 1.takes items of the list and sorts by frequency;
    # 2.takes a slice of the list starting from 8th element from the end
    # 3.reverses the list(just to look nice, dictionaries nowadays displyed ordered)
    # 4.creates new dictionary out of list of lists
    
    
    def filter_eight(req_list):
        return dict(sorted(req_list.items(), key=lambda x: x[1])[-8:][::-1])
    
    
    # Your request lists
    requests = [1, 13, 15, 1, 3, 4, 2, 12, 10,
                4, 1, 15, 15, 11, 14, 3, 4, 2, 1, 5, 3, 2, 4, 1, 2, 3, 4, 5, 12, 3, 4, 2, 34,  23, 1, 2, 3, 4, 12, 3, 12, 3, 4, 2, 3, 7, 10, 9, 14, 5]
    # data base
    req_data_base = {}
    # generator inside the list will execute
    [simulating_list(i, req_data_base) for i in requests]
    
    print(filter_eight(req_data_base))
    # Displays dictionary with key = request, value= frequency
    # If you want to display it differently its up to you
    # {3: 9, 4: 8, 2: 7, 1: 6, 12: 4, 5: 3, 15: 3, 14: 2}
    

    【讨论】:

      【解决方案3】:
      def fun(requests):
          freq={}
          for i in requests:
              if i in freq:
                  freq[i]+=1
                  print("hit",i)
              else:
                  freq[i]=1
                  print("miss",i)
              if len(freq)>8:
                  to_remove = min(freq,key=lambda k:(freq[k],k))
                  print("to remove",to_remove,"from",freq)
                  del freq[to_remove]
          return freq
      

      这类似于 Chris 的,但没有将东西转换为字符串,另一件事是使用 min 的 key 函数获取要删除的元素,我们使用对 (value) 作为比较键,key) 使用元组可排序的特性,并且它们的顺序由它们的值位置基数给出,因此如果它们在第一个位置具有相同的值(或在这种情况下为频率),请检查它的第二个位置,即我们的字典密钥(或给定的请求)

      >>> requests=[1, 13, 15, 1, 3, 4, 2, 12, 10, 4, 1, 15, 15, 11, 14, 7, 10, 9, 14, 5]
      >>> result=fun(requests)
      miss 1
      miss 13
      miss 15
      hit 1
      miss 3
      miss 4
      miss 2
      miss 12
      miss 10
      hit 4
      hit 1
      hit 15
      hit 15
      miss 11
      to remove 2 from {1: 3, 13: 1, 15: 3, 3: 1, 4: 2, 2: 1, 12: 1, 10: 1, 11: 1}
      miss 14
      to remove 3 from {1: 3, 13: 1, 15: 3, 3: 1, 4: 2, 12: 1, 10: 1, 11: 1, 14: 1}
      miss 7
      to remove 7 from {1: 3, 13: 1, 15: 3, 4: 2, 12: 1, 10: 1, 11: 1, 14: 1, 7: 1}
      hit 10
      miss 9
      to remove 9 from {1: 3, 13: 1, 15: 3, 4: 2, 12: 1, 10: 2, 11: 1, 14: 1, 9: 1}
      hit 14
      miss 5
      to remove 5 from {1: 3, 13: 1, 15: 3, 4: 2, 12: 1, 10: 2, 11: 1, 14: 2, 5: 1}
      >>> result
      {1: 3, 13: 1, 15: 3, 4: 2, 12: 1, 10: 2, 11: 1, 14: 2}
      >>> list(result)
      [1, 13, 15, 4, 12, 10, 11, 14]
      >>> 
              
      

      (还请注意,字典会默认遍历其键,因此实际上没有必要调用 .keys)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-21
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 2018-01-01
        • 2021-11-23
        相关资源
        最近更新 更多