【问题标题】:Get key by more than one value in dictionary?通过字典中的多个值获取键?
【发布时间】:2018-04-13 16:47:44
【问题描述】:

也许dict 不打算以这种方式使用,但我需要为同一个键添加多个值。我的意图是使用一种暂时的属性。如果我的字典是A:BB:C,那么我想要字典A:[B,C]

让我们举个例子来更好地解释我想做的事情:

numDict={'60':['4869'], '4869':['629'], '13':['2']}

我希望它返回:

{'60':['4869','629'], '13':['2']}

对于两个元素,可以这样使用:

result={}
for key in numDict.keys():
    if [key] in numDict.values():
        result[list(numDict.keys())[list(numDict.values()).index([key])]]=[key]+numDict[key]

但是如果我有更多元素呢?例如:

numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427'}

我该怎么做才能获得退回{'60':[4869,629,427'], '13':['2']}

【问题讨论】:

  • 那么到底是什么问题呢?你试过什么?
  • 我真的不认为这会很容易。字典在 python 中没有顺序,因此无法知道键是否在链的顶部。
  • 听起来你想要传递闭包,除了你还想在之后删除“中间”条目。您想如何处理循环引用,例如{1:[2], 2:[1]}?或者您确定不会发生循环?
  • MaorVeitsman 问题在于,如果有两个以上的元素,它就无法使用该代码,而且我不知道如何继续。 cᴏʟᴅsᴘᴇᴇᴅ 是的,我知道,但是哪种类型会更好? TomKarzes 我很确定不会有那些循环引用。
  • 查找“传递闭包”,并在其后使用 post-pass 删除每个具有前驱的节点(但请注意,您将在此过程中删除循环)。

标签: python dictionary get key


【解决方案1】:

我已经为它写了一个代码。看看有没有帮助。

我所做的是继续潜入直到我可以去(希望你理解这个声明)并将它们标记为已访问,因为它们将不再需要.最后我过滤掉 root 键。

numDict={'60':['4869'], '4869':['629'], '13':['2'], '629':['427']}

l = list(numDict) # list of keys
l1 = {i:-1 for i in numDict} # to track visited keys (initialized to -1 initially)

for i in numDict:
    # if key is root and diving in is possible
    if l1[i] == -1 and numDict[i][0] in l:
        t = numDict[i][0]
        while(t in l): # dive deeper and deeper
            numDict[i].extend(numDict[t]) # update the value of key
            l1[t] = 1 # mark as visited
            t = numDict[t][0]
# filter the root keys
answer = {i:numDict[i] for i in numDict if l1[i] == -1}
print(answer)

输出:

{'60': ['4869', '629', '427'], '13': ['2']}

【讨论】:

    【解决方案2】:

    您可以构建自己的结构,由(values, key) 的反向映射和(key, [values]) 的字典组成。添加key, value 对包括通过反向映射跟踪现有条目链,直到找到正确的位置;如果它不存在,它会引入一个新的键条目:

    class Groupir:
        def __init__(self):
            self.mapping = {}
            self.reverse_mapping = {}
    
        def add_key_value(self, k, v):
            self.reverse_mapping[v] = k
            val = v
            key = k
            while True:
                try:
                    self.reverse_mapping[val]
                    key = val
                    val = self.reverse_mapping[val]
                except KeyError:
                    try:
                        self.mapping[val].append(v)
                    except KeyError:
                        self.mapping[val] = [v]
                    break
    

    使用此测试客户端:

    groupir = Groupir()
    groupir.add_key_value(60, 4869)
    print(groupir.mapping)
    groupir.add_key_value(4869, 629)
    print(groupir.mapping)
    groupir.add_key_value(13, 2)
    print(groupir.mapping)
    groupir.add_key_value(629, 427)
    print(groupir.mapping)
    

    输出:

    {60: [4869]}
    {60: [4869, 629]}
    {60: [4869, 629], 13: [2]}
    {60: [4869, 629, 427], 13: [2]}
    

    限制:

    在 cmets 中提到的循环。
    非唯一键
    非唯一值
    可能需要处理一些极端情况。

    【讨论】:

      【解决方案3】:
      def unchain(d):
          #assemble a collection of keys that are not also values. These will be the keys of the final dict. 
          top_level_keys = set(d.keys()) - set(d.values())
      
          result = {}
          for k in top_level_keys:
              chain = []
              #follow the reference chain as far as necessary.
              value = d[k]
              while True:
                  if value in chain: raise Exception("Referential loop detected: {} encountered twice".format(value))
                  chain.append(value)
                  if value not in d: break
                  value = d[value]           
              result[k] = chain
          return result
      
      numDict={'60':'4869', '4869':'629', '13':'2', '629':'427'}
      print(unchain(numDict))
      

      结果:

      {'60': ['4869', '629', '427'], '13': ['2']}
      

      您可能会注意到我更改了numDict 的布局,因为如果值不是单元素列表,则处理起来会更容易。但是,如果您一心想保持这种方式,您只需将d = {k:v[0] for k,v in d.items()} 添加到unchain 的顶部,即可从一种转换为另一种。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-06
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        • 1970-01-01
        • 2011-12-21
        • 1970-01-01
        相关资源
        最近更新 更多