Bun*_*vis 27 python duplicates
我正在编写一些代码,我需要比较一些值。关键是所有变量都不应该具有相同的值。例如:
a=1
b=2
c=3
if a != b and b != c and a != c:
#do something
Run Code Online (Sandbox Code Playgroud)
现在,很容易看到在具有更多变量的代码的情况下,该if语句变得很长且充满ands。有没有一种简短的方法来告诉Python,没有2个变量值应该相同。
Tae*_*ung 48
您可以尝试进行设置。
a, b, c = 1, 2, 3
if len({a,b,c}) == 3:
# Do something
Run Code Online (Sandbox Code Playgroud)
如果将变量保存为列表,它将变得更加简单:
a = [1,2,3,4,4]
if len(set(a)) == len(a):
# Do something
Run Code Online (Sandbox Code Playgroud)
这是python集的官方文档。
正如问题中所给出的,这仅适用于可散列的对象,例如整数。对于非哈希对象,请参见@chepner的更一般的解决方案。
这绝对是你应该去哈希的对象的方式,因为它需要O(n)的时间为对象的数目ñ。不可哈希对象的组合方法花费O(n ^ 2)时间。
che*_*ner 25
假设不能使用散列,请使用itertools.combinations和all。
from itertools import combinations
if all(x != y for x, y in combinations([a,b,c], 2)):
# All values are unique
Run Code Online (Sandbox Code Playgroud)
MSe*_*ert 21
这取决于您拥有的值的种类。
如果它们表现良好且可哈希化,那么您可以(如其他人已经指出的那样)简单地使用a set来查找您拥有多少个唯一值,如果这不等于总值的数量,那么您至少有两个值是等于。
def all_distinct(*values):
return len(set(values)) == len(values)
all_distinct(1, 2, 3) # True
all_distinct(1, 2, 2) # False
Run Code Online (Sandbox Code Playgroud)
如果您确实有很多值,并且想在找到一个匹配项后立即中止,则也可以延迟创建该集合。如果所有值都不同,则更为复杂,并且可能会更慢,但是如果发现重复项,则会短路:
def all_distinct(*values):
seen = set()
seen_add = seen.add
last_count = 0
for item in values:
seen_add(item)
new_count = len(seen)
if new_count == last_count:
return False
last_count = new_count
return True
all_distinct(1, 2, 3) # True
all_distinct(1, 2, 2) # False
Run Code Online (Sandbox Code Playgroud)
但是,如果值不可哈希,则将无法使用,因为set需要可哈希值。
如果没有哈希值,则可以使用普通列表存储已处理的值,然后检查列表中是否已包含每个新项:
def all_distinct(*values):
seen = []
for item in values:
if item in seen:
return False
seen.append(item)
return True
all_distinct(1, 2, 3) # True
all_distinct(1, 2, 2) # False
all_distinct([1, 2], [2, 3], [3, 4]) # True
all_distinct([1, 2], [2, 3], [1, 2]) # False
Run Code Online (Sandbox Code Playgroud)
这会比较慢,因为检查值是否在列表中需要将其与列表中的每个项目进行比较。
如果您不介意其他依赖关系,则也可以使用我的一个库(在PyPi和conda-forge上可用)来完成此任务iteration_utilities.all_distinct。此函数可以处理可哈希值和不可哈希值(以及它们的混合):
from iteration_utilities import all_distinct
all_distinct([1, 2, 3]) # True
all_distinct([1, 2, 2]) # False
all_distinct([[1, 2], [2, 3], [3, 4]]) # True
all_distinct([[1, 2], [2, 3], [1, 2]]) # False
Run Code Online (Sandbox Code Playgroud)
请注意,上述所有方法均基于这样的事实,即相等意味着“不等于”(几乎)所有内置类型都是这种情况,但不一定如此!
但是,我想指出的是,cheapers答案不需要值的可哈希性,并且不通过显式检查来依赖“平等意味着不等于” !=。它还短路,因此其行为类似于您的原始and方法。
为了大致了解性能,我使用了我的另一个库(simple_benchmark)
我使用了不同的可哈希输入(左)和不可哈希输入(右)。对于可哈希输入,设置方法效果最好,而对于不可哈希输入,列表方法效果更好。combinations在两种情况下,基于方法的速度似乎最慢:
为了方便起见,我还测试了性能,为方便起见,我考虑了前两个元素相等的情况(否则设置与前面的情况相同):
from iteration_utilities import all_distinct
from itertools import combinations
from simple_benchmark import BenchmarkBuilder
# First benchmark
b1 = BenchmarkBuilder()
@b1.add_function()
def all_distinct_set(values):
return len(set(values)) == len(values)
@b1.add_function()
def all_distinct_set_sc(values):
seen = set()
seen_add = seen.add
last_count = 0
for item in values:
seen_add(item)
new_count = len(seen)
if new_count == last_count:
return False
last_count = new_count
return True
@b1.add_function()
def all_distinct_list(values):
seen = []
for item in values:
if item in seen:
return False
seen.append(item)
return True
b1.add_function(alias='all_distinct_iu')(all_distinct)
@b1.add_function()
def all_distinct_combinations(values):
return all(x != y for x, y in combinations(values, 2))
@b1.add_arguments('number of hashable inputs')
def argument_provider():
for exp in range(1, 12):
size = 2**exp
yield size, range(size)
r1 = b1.run()
r1.plot()
# Second benchmark
b2 = BenchmarkBuilder()
b2.add_function(alias='all_distinct_iu')(all_distinct)
b2.add_functions([all_distinct_combinations, all_distinct_list])
@b2.add_arguments('number of unhashable inputs')
def argument_provider():
for exp in range(1, 12):
size = 2**exp
yield size, [[i] for i in range(size)]
r2 = b2.run()
r2.plot()
# Third benchmark
b3 = BenchmarkBuilder()
b3.add_function(alias='all_distinct_iu')(all_distinct)
b3.add_functions([all_distinct_set, all_distinct_set_sc, all_distinct_combinations, all_distinct_list])
@b3.add_arguments('number of hashable inputs')
def argument_provider():
for exp in range(1, 12):
size = 2**exp
yield size, [0, *range(size)]
r3 = b3.run()
r3.plot()
# Fourth benchmark
b4 = BenchmarkBuilder()
b4.add_function(alias='all_distinct_iu')(all_distinct)
b4.add_functions([all_distinct_combinations, all_distinct_list])
@b4.add_arguments('number of hashable inputs')
def argument_provider():
for exp in range(1, 12):
size = 2**exp
yield size, [[0], *[[i] for i in range(size)]]
r4 = b4.run()
r4.plot()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3325 次 |
| 最近记录: |