【问题标题】:Checking for a dictionary key which is a range of integers检查一个整数范围的字典键
【发布时间】:2016-01-28 09:12:29
【问题描述】:

我正在建立一个制造商字典。它看起来像这样:

mfgs =     {17491: 'DS', 6543: 'AC'}

在这种情况下,我需要表示一个整数范围,它们都指向同一个制造商。 (比如1-99都是DC生产的)

我已经看到您可以创建一个表示范围的字典键。

mfgs =     {17491: 'DS', 6543: 'AC', (1,99): 'DC'}

稍后,我将从外部文件中获取一个整数。根据遇到的值,我会将相应的制造商记录到另一个文件中。

我不清楚如何检查是否存在有效的键/值对(无论是数字还是数字范围)并记录“未知”,如果没有建立扩展的 if/then 来说明键字典中定义的。

似乎 try/except 是合适的,但如果遇到 21,mfg[21] 会失败,它不应该。

【问题讨论】:

  • 其实这可能是一个更好的欺骗:stackoverflow.com/questions/15392623/…
  • 谢谢。我找到了第一个,但无法理解答案。 (Python 和编程新手。)。我会更仔细地阅读这些问题。
  • 酷!如果您对为什么那个人没有回答您的问题有具体问题,请随时提出另一个问题
  • 我认为只需要输入示例并运行它就可以看到它是如何工作的。也许理解会发生。 :)
  • 嗯,仔细检查后,它们都没有完全按照您在此处尝试执行的操作。我重新打开了这个问题并回答了它 - 希望它有所帮助!

标签: python if-statement dictionary range try-catch


【解决方案1】:

您需要的不仅仅是一个简单的 hashmap(即字典)查找。 Hashmaps 查找特定的键,而不是键是否在任何现有键的范围内。

你有两个简单的选择。

  1. 如果您提前知道范围,请在查找之前将整数转换为范围:

    def range_from_id(manufacturer_id):
        if 1 <= manufacturer_id <= 99:
            return (1, 99)
        return manufacturer_id
    
    manufacturer_id = ... from file ...
    manufacturer_range = range_from_id(manufacturer_id)
    manufacturer = mfgs.get(manufacturer_range, "Unknown")
    
  2. 如果不这样做,则在单独的字典中跟踪范围,并遍历所有可能的值:

    mfgs = {17491: 'DS', ...}
    mfg_ranges = {(1, 99): 'DC', ...}
    
    def lookup_manufacturer(manufacturer_id):
        # direct look-up:
        if manufacturer_id in mfgs: 
            return mfgs[manufacturer_id]
    
        # range look-up:
        for (start, end), mfg in mfg_ranges.items():
            if start <= manufacturer_id <= end:
                return mfg
    
        return "Unknown"
    

    如果速度很重要,请注意此选项将采用O(n),其中n 是您拥有的范围数。更合适的方法是使用二叉树,如amit answered here。这需要使用像bintrees 这样的第三方库。

【讨论】:

  • 那么对于选项二,您是在建议 two 字典吗?一个具有提前知道的 id,一个具有范围。对吗?
  • @tcv:是的。它使它更简单,因为它们确实是两种不同的查找策略。请注意,使用这种方法,您并没有真正利用范围字典的字典方面。它也可能是(start_range, end_range, id) 的列表 - 您正在遍历字典并手动检查所有范围。必须存在一个更有效地执行此操作的数据结构,但我不知道它是什么。
  • 我找到了另一种对我的 n00b 编程大脑有意义的方法。处理这个问题的最佳方法是什么?发布我的解决方案?还是接受你的?两者显然都可以工作。
  • @tcv:酷!如果它与我的不同,请发布并接受您自己的答案,这是完全可以接受的
  • 谢谢。我已经添加了它。它似乎对我很有效。任何其他制造商将被添加到其中的字典中。由于我的 n00b 状态,也许你可以告诉我我是否正在走向灾难。
【解决方案2】:

我找到了一种方法来做到这一点。请注意,我在那里是因为我们在一个 for 循环中遍历找到的项目。 mfgs 是一个预填充的字典。

try:
    drivers_list[i]['mfg'] = mfgs[mfg] # Attempt to store in dictionary
except:
    if 1 <= mfg <= 31:   # On exception, see if it's the known mfg.
        drivers_list[i]['mfg'] = 'The known manufacturer'  # Between 1 and 31
    else:
        drivers_list[i]['mfg'] = 'Unknown' # otherwise post unknown

【讨论】:

  • 关于告诉您是否正在走向灾难:如果您只有一个范围,即(1, 31),则此方法有效。但是如果你有两个范围,比如(1, 31)(39, 55),你会怎么做? 3个范围呢? n 范围呢?有比很多if/elif/elifs 更好的方法吗?
  • elif 将是我能想到的唯一方法。在这种情况下,我实际上只处理一个范围。我正在编目旧计算机的硬件制造商 Apple ///。 1-31 是苹果电脑。很少有第三方制造硬件,所以我很可能不会遇到另一个范围。不过,我想我会把你的建议付诸实践,以便更好地理解它。至少现在完成它的焦虑已经结束了!
  • 酷!作为提示,当您发现自己一遍又一遍地编写相同的代码时,其中只有一些变化(例如if 1 &lt;= mfg &lt;= 31: ... if 39 &lt;= mfg &lt;= 55: ...),然后考虑将变化的东西(在这种情况下为开始和结束值)放入数据结构中(像一个列表或一个字典),并循环通过它。
猜你喜欢
  • 2014-11-01
  • 2011-06-08
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多