【问题标题】:Python looping over dictionary to substitute keys with the values from another dictionaryPython循环遍历字典以用另一个字典中的值替换键
【发布时间】:2013-04-02 21:56:42
【问题描述】:

我有一本字典,我想将该字典中的所有键更改为另一个字典中的值。

例如:

X = {"apple" : 42}

Y = {"apple" : "Apples"}

转换后:

字典X = {"Apples" : 42}

def convert(items, ID):
    for key, value in items.items():
        for keys, values in ID.items():
            if keys == key:
                key = values
    return items

所以我写了上面的代码来做到这一点,但是在执行这个函数之后,我打印了字典并且键没有改变。

【问题讨论】:

    标签: python loops dictionary


    【解决方案1】:

    这是因为您正在为局部变量分配新值,而不是为字典键分配新值。

    但是,为了获得所需的结果,我建议按照其他人的建议并创建一个新字典,因为您的键与任何现有字典都不对齐:

    如果您想这样做,您必须通过字典赋值显式设置值:

    def convert(X, Y):
        new_dict = {}
        for x_key, x_value in X.items():
            for y_key, y_value in Y.items():
                if x_key == y_key:
                    new_dict[y_value] = x_value
    
        return new_dict
    

    【讨论】:

    • 这不会用新字典的值更新旧键,而是将新字典上的值分配给旧字典。键。
    • 我认为 Oliver 是否想更新项目或 ID 的问题不是 100% 清楚......我认为他想更新字典“项目”而不是“ID”。编辑:只需重新阅读问题。我的回答不会提供所需的结果。
    • 该示例显示了将 ID dict 中的values 分配给项目一的key,他提出的问题是键没有改变。我也不是 100% 确定,但我相信他想更新键,因为他在第一句话中说 我想将一个字典中的键更改为另一个字典中的值跨度>
    • 是的,谢谢,我知道他想要的东西与我的第一个答案完全不同,所以我相应地进行了更改。
    • 是的 Mariano,这就是我想要达到的目的,如果问题不完全清楚,请见谅。现在解决了,谢谢大家的回复:)
    【解决方案2】:

    在您的第一个循环中,您正在迭代 (key, value) 对。更改 key 变量的值不会在字典中更新它。

    您需要做的是将value 重新分配给新的key (values) 和del 旧密钥。此示例创建一个新副本,因此它不会就地修改 dict。我还删除了内部 for loop,因为在 python 中,您只需检查密钥是否在字典中,而无需使用 if key in dictionary 遍历所有密钥。

    def convert(items, id):
        new_dict = items.copy()
        for key, value in items.items():
            if key in id:
                new_key = id[key]
                new_dict[new_key] = items[key] # Copy the value
                del new_dict[key]
        return new_dict
    

    示例 ipython 会话:

    In [1]: items = {'apple': 42, 'orange': 17}
    
    In [2]: new_keys = {'apple': 'banana', 'orange': 'tangerine'}
    
    In [3]: def convert(items, ID):
                ...
    
    In [13]: convert(items, new_keys)
    Out[13]: {'banana': 42, 'tangerine': 17} # Updated dict returned
    
    In [14]: items
    Out[14]: {'apple': 42, 'orange': 17} # Original dict stays untouched
    

    【讨论】:

      【解决方案3】:

      当您调用 items.items() 时,您正在创建字典的 (key, value) 对的副本。

      因此,当您更改 key 的值时,您更改的是副本的值,而不是原始值。

      def convert(items, ID):
          for key, value in items.items():
              for keys, values in ID.items():
                  if keys == key:
                      items[key] = values
          return items
      

      【讨论】:

        【解决方案4】:

        方法

        使用集合交集计算共享密钥。

        2.7 之前的代码

        def convert(items, ID):
            # Find the shared keys
            dst, src = set(items.keys()), set(ID.keys())
            same_keys, diff_keys = dst.intersection(src), dst.difference(src)
            # Make a new dictionary using the shared keys
            new_values = [(ID[key], items[key]) for key in same_keys]
            old_values = [(key, items[key]) for key in diff_keys]
            return dict(new_values + old_values)
        

        2.7+ 的代码

        def convert(items, ID):
            # Find the shared keys
            dst, src = set(items.keys()), set(ID.keys())
            same_keys, diff_keys = dst.intersection(src), dst.difference(src)
            # Make a new dictionary using the shared keys
            new_values = {ID[key]: items[key] for key in same_keys}
            old_values = {key: items[key] for key in diff_keys}
            return reduce(lambda dst, src: dst.update(src) or dst, [new_values, old_values], {})
        

        2.7 之前的测试

        >>> def convert(items, ID):
        ...     # Find the shared keys
        ...     dst, src = set(items.keys()), set(ID.keys())
        ...     same_keys, diff_keys = dst.intersection(src), dst.difference(src)
        ...     # Make a new dictionary using the shared keys
        ...     new_values = [(ID[key], items[key]) for key in same_keys]
        ...     old_values = [(key, items[key]) for key in diff_keys]
        ...     return dict(new_values + old_values)
        ... 
        >>> convert({"apple" : 42, "pear": 38}, {"apple" : "Apples", "peach": 31})
        {'pear': 38, 'Apples': 42}
        

        测试 2.7+

        >>> def convert(items, ID):
        ...     # Find the shared keys
        ...     dst, src = set(items.keys()), set(ID.keys())
        ...     same_keys, diff_keys = dst.intersection(src), dst.difference(src)
        ...     # Make a new dictionary using the shared keys
        ...     new_values = {ID[key]: items[key] for key in same_keys}
        ...     old_values = {key: items[key] for key in diff_keys}
        ...     return reduce(lambda dst, src: dst.update(src) or dst, [new_values, old_values], {})
        ... 
        >>> convert({"apple" : 42, "pear": 38}, {"apple" : "Apples", "peach": 31})
        {'pear': 38, 'Apples': 42}
        

        【讨论】:

          【解决方案5】:

          您是否有理由需要修改现有字典而不仅仅是创建一个新字典?

          要通过创建一个新字典来完成同样的任务,试试这个:

          def convert(items, ID):
              result = {}
              for key, value in items.items():
                  if key in ID.keys():
                      result[ID[key]] = value
                  else:
                      result[key] = value
              return result
          

          如果你真的想修改原来的字典,无论如何你都想创建一个临时的新字典,然后用新字典的内容填充原来的字典,像这样

          def convert(items, ID):
              result = {}
              for key, value in items.items():
                  if key in ID.keys():
                      result[ID[key]] = value
                  else:
                      result[key] = value
              items.clear()
              for key, value in result.items():
                  items[key] = value
              return items 
          

          如果您不这样做,那么您必须担心覆盖值,即您尝试将键重命名为已经存在的内容。这是我的意思的一个例子:

          items = {"apples": 10, "bananas": 15}
          ID = {"apples": "bananas", "bananas": "oranges"}
          convert(items, ID)
          print items
          

          我假设您想要的行为是以{"bananas": 10, "oranges": 15} 结尾的。如果它首先将"apples" 重命名为"bananas" 会怎样?然后你有{"bananas": 10},然后会变成{"oranges": 10}

          最糟糕的是,它完全取决于 python 遍历键的顺序,这取决于您首先添加它们的顺序。如果这在未来的 python 版本中发生了变化,那么你的程序的行为可能会发生变化,这是你绝对想要避免的。

          【讨论】:

            【解决方案6】:

            您的问题是您在字典或其键和值的新本地副本中工作

            如果问题是返回一个新字典,这将在一行中工作

            def convert(x,y):
                return dict( (y.get(k,k), x[k]) for k in x )
            x={'a':10, 'b':5}
            y={'a':'A'}
            print convert(x,y)
            

            在 python 2.7+ 中你甚至可以

            def convert(x,y):
                 return { y.get(k,k): x[k] for k in x }
            

            但如果你想在同一个输入字典中工作,那么

            def convert(x,y):
                 r={ y.get(k,k): x[k] for k in x }
                 for k in x.keys(): del x[k]
                 x.update(r)
            
            x={'a':10, 'b':5}
            y={'a':'A'}
            convert(x,y)
            print x
            

            【讨论】: