Python:如果字典中的两个键具有相同的值,我如何引发错误?

Python:如果字典中的两个键具有相同的值,我如何引发错误?,python,python-2.7,dictionary,Python,Python 2.7,Dictionary,我编写了一个在字典中交换键和值的函数 def reverse_dict(my_dict): my_dict2 = dict((v,k) for k,v in my_dict.iteritems()) return my_dict2 为此,我不能有具有相同值的不同键。 例如: 如果一个值在输入字典中出现多次,我如何抛出一个ValueError。只要检查len(my_dict 2)==len(my_dict)。如果长度不相同,请提高ValueError def reverse_di

我编写了一个在字典中交换键和值的函数

def reverse_dict(my_dict):
    my_dict2 = dict((v,k) for k,v in my_dict.iteritems())
    return my_dict2
为此,我不能有具有相同值的不同键。 例如:


如果一个值在输入字典中出现多次,我如何抛出一个
ValueError

只要检查
len(my_dict 2)==len(my_dict)
。如果长度不相同,请提高
ValueError

def reverse_dict(my_dict):
    my_dict2 = dict((v,k) for k,v in my_dict.iteritems())
    if len(my_dict2) != len(my_dict):
        raise ValueError('Disallowed duplicate value in dictionary')
    return my_dict2

如注释所示,您可以使用dict理解而不是
dict
和生成器表达式:

my_dict2 = {v: k for k,v in my_dict.iteritems()}

如果你真的以python2.7+为目标的话,它会更简洁(而且性能更好)

只需检查
len(my_dict 2)==len(my_dict)
。如果长度不相同,请提高
ValueError

def reverse_dict(my_dict):
    my_dict2 = dict((v,k) for k,v in my_dict.iteritems())
    if len(my_dict2) != len(my_dict):
        raise ValueError('Disallowed duplicate value in dictionary')
    return my_dict2

如注释所示,您可以使用dict理解而不是
dict
和生成器表达式:

my_dict2 = {v: k for k,v in my_dict.iteritems()}

如果你真的以python2.7+为目标,那么它会稍微简洁一些(而且性能更好),你可以跳过理解,边看边看:

#!python2
def reverse_dict(my_dict):
    my_dict2 = {}
    for k,v in my_dict.iteritems():
        if v not in my_dict2:
            my_dict2[v] = k
        else:
            raise ValueError(v)
    return my_dict2

random_dict = {"a" : 1, "b" : 2, "c" : 1}
random_dict2 = reverse_dict(random_dict)
输出:

Traceback (most recent call last):
  File "C:\test.py", line 12, in <module>
    random_dict2 = reverse_dict(random_dict)
  File "C:\test.py", line 8, in reverse_dict
    raise ValueError(v)
ValueError: 1
回溯(最近一次呼叫最后一次):
文件“C:\test.py”,第12行,在
随机记录2=反向记录(随机记录)
文件“C:\test.py”,第8行,相反
提升值错误(v)
值错误:1

通过这种方式,您还可以获得副本值的指示。

您可以跳过理解,边走边检查:

#!python2
def reverse_dict(my_dict):
    my_dict2 = {}
    for k,v in my_dict.iteritems():
        if v not in my_dict2:
            my_dict2[v] = k
        else:
            raise ValueError(v)
    return my_dict2

random_dict = {"a" : 1, "b" : 2, "c" : 1}
random_dict2 = reverse_dict(random_dict)
输出:

Traceback (most recent call last):
  File "C:\test.py", line 12, in <module>
    random_dict2 = reverse_dict(random_dict)
  File "C:\test.py", line 8, in reverse_dict
    raise ValueError(v)
ValueError: 1
回溯(最近一次呼叫最后一次):
文件“C:\test.py”,第12行,在
随机记录2=反向记录(随机记录)
文件“C:\test.py”,第8行,相反
提升值错误(v)
值错误:1

通过这种方式,您还可以获得复制值的指示。

您还可以检查
random\u dict.values()
的长度是否不等于
set(random\u dict.values())

让我们看看:

>>> random_dict = {"a" : 1, "b" : 2, "c" : 1}
>>> len(random_dict.values())
3
>>> len(set(random_dict.values()))
2
>>> random_dict.values()
dict_values([1, 2, 1])
>>> set(random_dict.values())
{1, 2}
所以很简单:

>>> if not len(random_dict.values()) == len(set(random_dict.values())):
...     raise ValueError
... 
Traceback (most recent call last):
  File "<input>", line 2, in <module>
    raise ValueError
ValueError
>>如果不是len(random_dict.values())==len(set(random_dict.values()):
...     升值误差
... 
回溯(最近一次呼叫最后一次):
文件“”,第2行,在
升值误差
数值误差

您还可以检查
random\u dict.values()
的长度是否不等于
set(random\u dict.values())

让我们看看:

>>> random_dict = {"a" : 1, "b" : 2, "c" : 1}
>>> len(random_dict.values())
3
>>> len(set(random_dict.values()))
2
>>> random_dict.values()
dict_values([1, 2, 1])
>>> set(random_dict.values())
{1, 2}
所以很简单:

>>> if not len(random_dict.values()) == len(set(random_dict.values())):
...     raise ValueError
... 
Traceback (most recent call last):
  File "<input>", line 2, in <module>
    raise ValueError
ValueError
>>如果不是len(random_dict.values())==len(set(random_dict.values()):
...     升值误差
... 
回溯(最近一次呼叫最后一次):
文件“”,第2行,在
升值误差
数值误差
您只需要:

values = my_dict.values()
if len(values) != len(set(values)):
    raise ValueError
在转置键和值之前

def reverse_dict(my_dict):
    values = my_dict.values()
    if len(values) != len(set(values)):
        raise ValueError
    my_dict2 = dict((v,k) for k,v in my_dict.iteritems())
    return my_dict2
您所需要的只是:

values = my_dict.values()
if len(values) != len(set(values)):
    raise ValueError
在转置键和值之前

def reverse_dict(my_dict):
    values = my_dict.values()
    if len(values) != len(set(values)):
        raise ValueError
    my_dict2 = dict((v,k) for k,v in my_dict.iteritems())
    return my_dict2

检查当前值是否已经作为键存在于结果dict中。但是你应该发布你的函数-它可能需要另一种方法来实现。你可以在计数器(my_dict.values())中找到重复的值,如果v>1,则可以找到项(),如果你需要知道它们是什么,只需在遍历时检查当前值是否已经作为键存在于结果dict中。但是你应该发布你的函数——它可能需要另一种方式来实现。你可以在计数器(my_dict.values())中找到重复的值,如果v>1,则为items()如果你需要知道它们是什么,为什么不是dict理解?@johnlaroy——因为OP没有使用。也许OP出于这样或那样的原因想保持与python2.6的向后兼容性。为什么不用听写理解?@johnlaroy——因为OP没有使用听写理解。也许OP出于这样或那样的原因想保持与python2.6的向后兼容性。在下一步(你可以在上面执行相同的检查)中已经要构建另一个dict时,构建一个一次性集似乎是一种浪费@mgilson你建议在创建一个新dict后进行检查,而我是说在创建一个新dict之前进行检查。两者都有优点。为什么?之前检查有什么好处?在普通情况下,您将使用更多的内存,并且所用的时间大约是普通情况下的两倍(没有例外)。在不常见的情况下,您在python3.x上节省了大约一半的dict内存,但在python2.x上却没有这么多,因为
dict.values()
还创建了一个新列表……好的。如果普通情况也不例外,那么我同意你的观察。OP没有提到任何关于dict长度或值分布的内容。在下一步(您可以在其上执行相同的检查)中构建另一个dict时,构建一次性集合似乎是浪费@mgilson您建议在创建新dict后进行检查,当我说在创建一个新的dict之前检查一下。两者都有优点。为什么?之前检查有什么好处?在普通情况下,您将使用更多的内存,并且所用的时间大约是普通情况下的两倍(没有例外)。在不常见的情况下,您在python3.x上节省了大约一半的dict内存,但在python2.x上却没有这么多,因为
dict.values()
还创建了一个新列表……好的。如果普通情况也不例外,那么我同意你的观察。OP没有提到任何关于dict的长度或值的分布。更正——您将得到一个重复值的指示。如果有多个重复,您将只看到一个。除此之外,我喜欢这个答案。这是唯一一个有机会提前短路的(尽管必须对实际数据进行实际测量,以确定这对OP的平均情况是否有好处)+我给你的。@mgilson,谢谢,因此注释
是一种指示。与大多数异常一样,修复引发异常的异常,然后下一个错误(重复)将引发:)更正——您将得到一个重复值的指示。如果有多个重复,您将只看到一个。除此之外,我喜欢这个答案。这是唯一一个有可能早期短路的(尽管必须对实际数据进行实际测量才能看到)