我正在编写一些代码,我需要比较一些值。关键是所有变量都不应该具有相同的值。例如:
import React from 'react';
import { Platform, StatusBar, StyleSheet, View, AsyncStorage} from 'react-native';
import { AppLoading, Asset, Font, Icon } from 'expo';
import AppNavigator from './navigation/AppNavigator';
import MainTabNavigator from './navigation/MainTabNavigator';
import * as firebase from 'firebase';
export default class App extends React.Component {
state = {
isLoadingComplete: false,
isAuthenticationReady: false,
isAuthenticated: false,
};
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="default" />}
<AppNavigator />
</View>
);
}
}
_loadResourcesAsync = async () => {
return Promise.all([
Asset.loadAsync([
require('./assets/images/robot-dev.png'),
require('./assets/images/robot-prod.png'),
]),
Font.loadAsync({
// This is the font that we are using for our tab bar
...Icon.Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free
// to remove this if you are not using it in your app
'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf'),
}),
]);
};
现在,很容易看到在具有更多变量的代码的情况下,a=1
b=2
c=3
if a != b and b != c and a != c:
#do something
语句变得很长,充满了if
s。有没有一种简短的方法来告诉Python,没有2个变量值应该相同。
答案 0 :(得分:45)
您可以尝试进行设置。
a, b, c = 1, 2, 3
if len({a,b,c}) == 3:
# Do something
如果将变量保存为列表,它将变得更加简单:
a = [1,2,3,4,4]
if len(set(a)) == len(a):
# Do something
Here是python集的官方文档。
这仅适用于问题中给出的可哈希对象(例如整数)。对于非哈希对象,请参见@chepner的more general solution。
这绝对是您应该使用可哈希对象的方式,因为对象数量 n 花费O(n)时间。不可散列对象的组合方法需要O(n ^ 2)的时间。
答案 1 :(得分: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
答案 2 :(得分:19)
这取决于您拥有的值的类型。
如果它们表现良好且可哈希化,那么您可以(如其他人已经指出的那样)简单地使用set
来找出您拥有多少个唯一值,如果它们不等于总值的数量您至少有两个相等的值。
def all_distinct(*values):
return len(set(values)) == len(values)
all_distinct(1, 2, 3) # True
all_distinct(1, 2, 2) # False
如果您确实有很多值,并且想在找到一个匹配项后立即中止,则也可以延迟创建该集合。如果所有值都不相同,它会更复杂,并且可能会更慢,但如果发现重复项,则会短路:
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
但是,如果值不可哈希,则将无法正常工作,因为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
这会比较慢,因为检查值是否在列表中需要将其与列表中的每个项目进行比较。
如果您不介意其他依赖关系,也可以将我的一个库(在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
请注意,上述所有方法都依赖于这样一个事实,即相等意味着“不等于”(几乎)所有内置类型都是这种情况,但不一定如此!
但是我想指出chepners answers,它不需要对值进行散列,并且并不通过显式检查{{ 1}}。它还会短路,因此其行为类似于您最初的!=
方法。
要大致了解性能,我正在使用我的另一个库(simple_benchmark
)
我使用了不同的可哈希输入(左)和不可哈希输入(右)。对于可散列的输入,设置方法的效果最好,而对于不可散列的输入,列表方法的效果更好。在两种情况下,基于and
的方法似乎最慢:
我还测试了有重复的情况下的性能,为方便起见,我考虑了前两个元素相等的情况(否则设置与前面的情况相同):
combinations
答案 3 :(得分:1)
稍微整洁的方法是将所有变量粘贴在列表中,然后从列表中创建一个新集合。如果列表和集合的长度不同,则某些变量相等,因为集合不能包含重复项:
vars = [a, b, c]
no_dupes = set(vars)
if len(vars) != len(no_dupes):
# Some of them had the same value
这假定值是可哈希的;它们在您的示例中。
答案 4 :(得分:0)
您也可以将all
与list.count
一起使用,这是合理的,可能不是最好的方法,但是值得回答:
>>> a, b, c = 1, 2, 3
>>> l = [a, b, c]
>>> all(l.count(i) < 2 for i in l)
True
>>> a, b, c = 1, 2, 1
>>> l = [a, b, c]
>>> all(l.count(i) < 2 for i in l)
False
>>>
此解决方案还适用于列表中不可散列的对象。
仅适用于列表中的可哈希对象的方法:
>>> a, b, c = 1, 2, 3
>>> l = [a, b, c]
>>> len({*l}) == len(l)
True
>>>
实际上:
>>> from timeit import timeit
>>> timeit(lambda: {*l}, number=1000000)
0.5163292075532642
>>> timeit(lambda: set(l), number=1000000)
0.7005311807841572
>>>
{*l}
比set(l)
更快,更多信息here。