【问题标题】:Python dealing with reverse lookupPython处理反向查找
【发布时间】:2012-10-18 00:20:49
【问题描述】:

我有 20 个匹配 20 个整数的字符串。所有整数和字符串都是唯一的。我正在考虑但想避免创建两个字典。一本字典会被字符串索引,一本字典会被整数索引。

  • 我应该如何处理这种情况?

我创建了两个列表。一个包含字符串,另一个包含整数。我正在考虑构建两个功能。一个函数将产生一个字符串。另一个函数将产生一个整数。另一种选择是如果产生的参数是整数或字符串,则通过分支将它们组合成一个函数。

  • 这与字典有什么可比性?会不会消耗很多cpu? (此功能每天会运行 数百万 次)
  • 我是否应该创建一个元组列表,这些元组是 (string, int),然后 创建两个字典,一个映射 int 到列表位置,另一个 列出位置的字符串?这会是最好的方式吗?

我没有很多东西,所以我可以牺牲一些记忆。

请解释最好的方法并解释为什么它是最好的。

谢谢。

【问题讨论】:

  • 您反对拥有两本词典的原因是什么?只要您从另一个自动生成一个,而不是独立定义它们,这似乎是最直接的解决方案。
  • @MarkReed,听起来有点不对劲。我是 Python 新手,我认为会有更好的方法来创建一个实体,就像在字典上进行反向查找一样。就这样。你觉得是这样吗?

标签: python python-2.7


【解决方案1】:

为什么不使用 1 个双向映射的字典?

ints = list(range(10))
strs = [str(x) for x in ints]
d = dict(zip(ints,strs))
d.update(zip(strs,ints))

print repr(d[1])   # '1'
print repr(d['1']) # 1

既然你有唯一的字符串和唯一的整数,那么这两个集合的并集也应该是一个唯一的列表,其中包含其他两个集合中的所有元素。把它们都放在字典里应该没有问题

【讨论】:

  • 嗨@mgilson!正如我在问题中所说的那样,我想到了这一点,但正如我在上面向@MarkReed 解释的那样,它似乎不是反向查找的优雅解决方案。你认为这是正确的做法吗?
  • @Phil -- 我认为它没有任何错误。我认为实际的解决方案可能很大程度上取决于您实际计划使用此映射做什么。不过,与在列表中使用 .index 相比,这将在计算上更加高效。
【解决方案2】:

无论您采用哪种解决方案,如果您希望它健壮,您可能应该在它周围包装一个类,当您更新一个时,它会自动更新另一个方向。例如,这是一个使用@mgilson 技术的基本双向字典的开始(这意味着如果您要相互映射的两组项目之间有任何重叠,它将无法工作;但具有不同类型的效果很好):

class BiDict(dict):
  """Bidirectional Dictionary - setting 'key' to 'value' also
     sets 'value' to 'key' (so don't use overlapping mappings)
  """

  def __init__(self, *args):
    super(BiDict, self).__init__(*args)

    # After regular dict initialization, loop over any items
    # and add their reverse.  Note that we can't use any of the
    # iter* methods here since we're adding items in the body
    # of the loop.
    for key in self.keys():
      super(BiDict, self).__setitem__(self[key], key);


  def __setitem__(self, key, val):
    # If the key has an old value, delete its reverse
    if key in self:
      super(BiDict, self).__delitem__(self[key])

    # Then add both forward and reverse for the new value
    super(BiDict, self).__setitem__(key, val);
    super(BiDict, self).__setitem__(val, key);

  def __delitem__(self, key):
    # delete both directions
    if key in self:
      super(BiDict, self).__delitem__(self[key]);
      super(BiDict, self).__delitem__(key);

你可以这样使用它:

>>> from bidict import BiDict
>>> d = BiDict({'a':1,'b':2})
>>> d['a']
1
>>> d[2]
'b'
>>> d['c']=3
>>> d[3]
'c'
>>> del d['a']
>>> d['a']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'a'
>>> d[1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 1

【讨论】:

  • 非常感谢您的时间和努力。我会这样走。
猜你喜欢
  • 2015-09-27
  • 2021-07-08
  • 2012-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多