【问题标题】:Return value of largest key if key not found in defaultdict如果在 defaultdict 中找不到键,则返回最大键的值
【发布时间】:2021-09-03 09:10:15
【问题描述】:

要求

如果我提供的键不在字典中,我想定义一个返回最大键的值的defaultdict。基本上我正在寻找一种方法来存储配置信息的扭曲,这些值默认为其最后定义的值。

目前的解决方案

我的实现如下:

from collections import defaultdict

d = defaultdict(lambda: d[max(d.keys())])
d.update({2010: 10, 2011: 20, 2013: 30 })

for year in [2010, 2011, 2013, 2014]:
    print(f"{year}: {d[year]}")

正确产生:

2010: 10
2011: 20
2013: 30
2014: 30

(更复杂的版本也可以返回小于最小键的值)。

问题

有没有更优雅的方式来定义 lambda 函数而不要求您知道字典的名称?

【问题讨论】:

  • 当有很多键时,每次搜索最大的键会变得非常慢。这听起来不像是默认字典的工作。
  • 另外,请记住,当您查找丢失的键时,defaultdicts 插入默认值。这听起来不像您在这里需要的行为。

标签: python defaultdict


【解决方案1】:

频繁计算最大键看起来效率很低,因为在 Python 中键位于哈希映射中,因此它们没有排序。

考虑编写自己的 default_dict:

class DictLast(collections.MutableMapping,dict):
    def __init__(self, *args, **kwargs):
        self.theMaxKey = None 
        self.update(*args, **kwargs)
    def __getitem__(self, key):
        if dict.__contains__(self,key): 
            return dict.__getitem__(self,key)
        return dict.__getitem__(self, self.theMaxKey)
    def __setitem__(self, key, value):
        if self.theMaxKey is None:
            self.theMaxKey = key
        if key > self.theMaxKey: 
            self.theMaxKey = key
        dict.__setitem__(self,key,value)   

d = DictLast()
d.update({2010: 10, 2011: 20, 2013: 30 })

for year in [2010, 2011, 2013, 2014]:
    print(f"{year}: {d[year]}")

请注意,每当要求丢失密钥时, 我的实现没有将键添加到字典中。我认为这是预期的行为

如果您有疑问,请在我和您的实现中尝试以下代码:

for year in [2010, 2011, 2013, 2015]:
    print(f"{year}: {d[year]}")
d[2014]=7
for year in [2010, 2011, 2013, 2015]:
    print(f"{year}: {d[year]}")

了解有什么区别

编辑: 正如下面的 cmets 所指出的:

“此策略仅在您不从字典中删除项目时才有效”。

IMO 如果您希望数据结构设计得很好,您也应该管理删除(由您决定是否要提高、重新计算最大值或做一些不同的事情)。

【讨论】:

  • 请注意,此策略仅在您不从字典中删除项目时才有效。
  • @kaya3 你是对的!编辑是有序的。如果 dict 不打算用于删除,则提出;如果删除不频繁,则重新计算 maxkey;否则重新考虑数据结构。谢谢
  • 这里为什么需要MutableMappingdict 已经 is one。请注意,对于 python3.9,您需要编写 collections.abc.MutableMapping 以避免出现弃用警告。
  • 如果从MutableMapping 重新继承的主要原因是__setitem__() 也被dict.update() 调用,那么我不确定这是否是正确的方法。 (继承顺序在你的类定义中很重要,试试看。)
  • @jimifiki 修改内置的 python 类总是很棘手......请参阅this related post。我认为您必须覆盖更多的 dict 方法(例如 __delitem__updatesetdefault)才能使您的方法正常工作。
【解决方案2】:

不确定您是否需要在此处使用defaultdictdefaultdict 的主要用途是在未找到请求的键时插入并设置默认值。但是,在最初的问题中,似乎不需要此功能。

相反,我只是使用自定义字典:

class CustomDict(dict):
    def __getitem__(self, key):
        if key not in self.keys():
            key = max(self.keys())
        return super().__getitem__(key)

如果您出于某种原因确实需要defaultdict,您可以进行类似操作并从defaultdict 派生。

【讨论】:

    猜你喜欢
    • 2023-02-13
    • 2016-10-04
    • 1970-01-01
    • 2021-01-27
    • 2021-08-03
    • 2021-06-28
    • 1970-01-01
    • 2018-09-12
    • 2014-05-18
    相关资源
    最近更新 更多