我想一次测试多个不等式,即
if (a < b < c < ...)
当所有值都存在时,这很好。但是,有时一个或多个要比较的变量的数值可能会丢失/未知;我的上下文中的正确行为是假设满足相关的不等式。假设我在值未知时分配特殊值None
:我想从<
运算符(或替代方法)执行的行为是:
>>> a = 1; b = 2; c = 3
>>> a < b < c # this works fine, obviously
True
>>> b = None
>>> a < b < c # would like this to return True
False
所以我想得到True
如果一个变量真的小于另一个变量,或者如果一个变量缺失(取任何特定的预定非数值),或者两个变量都缺失了,我希望能够将比较串起来,即a < b < c < ...
我还希望<=
以及<
执行此操作
感谢
答案 0 :(得分:5)
您想测试序列 - 禁止未定义的值 - 是否按升序排列:
import operator
def isAscending(strictly, *seq):
cmp_op = operator.lt if stricly else operator.le
seq = [e for e in seq if e is not None]
return all(cmp_op(a, b) for a, b in zip(seq, seq[1:]))
a, b, c = 1, None, 2
print isAscending(True, a, b, c) # strictly ascending ?
编辑拼写,并按照建议使用比较运算符。
答案 1 :(得分:2)
看起来您实际上正在尝试测试您的值是否是唯一的并且按照排序顺序可以替换为:
>>> def my_test(l):
>>> filt_l = [v for v in l if not v is None]
>>> return (sorted(filt_l) == filt_l) and (len(filt_l) == len(set(filt_l)))
>>> my_test([1,2,3])
True
>>> my_test([1,None,3])
True
>>> my_test([1,4,3])
False
>>> my_test([1,1,3])
False
编辑包括时间似乎sebdelsol建议的功能更快
>>> %timeit isAscending([int(1000*random.random()) for i in xrange(10000)])
100 loops, best of 3: 3.44 ms per loop
>>> %timeit my_test([int(1000*random.random()) for i in xrange(10000)])
100 loops, best of 3: 5.67 ms per loop
答案 2 :(得分:1)
您可以创建自己的类型重载比较方法(如此问题:python overloading operators)
E.g。
class N(object):
def __init__(self, value):
self.value = value
def __lt__(self, other):
return (self.value is None or self.value < other.value)
...
a = N(1); b = N(None); c = N(3)
print a < b < c
答案 3 :(得分:1)
如果您在列表中有值([a, b, c]
),那么您可以从中过滤无值,使用zip()
将它们配对,将运算符应用于所有对,并查看是否全部他们坚持。
在代码中:
import operator # For operator.lt, which is < ("less than")
def mass_comparify(op, *args):
return all(op(a, b) for a, b in zip(args, args[1:])
if a is not None and b is not None)
print(mass_comparify(operator.lt, 1, None, 3)) # Prints True because 1 < 3
答案 4 :(得分:0)
我认为你没有比定义比较函数更好的选择,比较函数可以根据需要进行比较,然后将不等式写成
comp(a,b) and comp(b,c) and ...
答案 5 :(得分:0)
我不知道它是否完全适合,但您可以使用reduce
:
>>> import operator
>>> reduce(operator.__lt__, [1, None, 3])
True
>>> reduce(operator.__lt__, [1, None, 0])
False
或者更加可靠,因为它明确地忽略了无值:
>>> import operator
>>> reduce(operator.__lt__, filter(None, [1, None, 3]))
True
>>> reduce(operator.__lt__, filter(None, [1, None, 0]))
False