多个不等式 (a < b < c...) 可能有缺失值

2 投票
6 回答
3594 浏览
提问于 2025-04-19 19:31

我想一次性测试多个不等式,也就是:

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 < ...
我也想用<=来做同样的事情,除了<以外。
谢谢

6 个回答

0

我觉得你没有比定义一个比较函数更好的选择,这个函数可以按照你想要的方式进行比较。然后你可以把不等式写成:

comp(a,b) and comp(b,c) and ...
1

如果你有一个列表,比如说 [a, b, c],你可以把里面的 None 值过滤掉,然后用 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
1

你可以自己创建一些比较方法来实现类型重载(就像这个问题中提到的:python 重载运算符

比如说:

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
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
5

你想要检查一下你的序列(除了那些未定义的值)是否是按顺序排列的,也就是从小到大:

import operator

def isAscending(strictly, *seq):
    cmp_op = operator.lt if strictly 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 ?

这个内容经过了拼写修正,并且根据建议使用了比较运算符。

撰写回答