检查列表中的所有数字是否与Python中的符号相同?

时间:2013-01-28 20:57:28

标签: python list python-2.7 sign

如何确定列表(或可迭代)的数字是否都具有相同的符号?

这是我的第一个(幼稚)草案:

def all_same_sign(list):

    negative_count = 0

    for x in list:
        if x < 0:
            negative_count += 1

    return negative_count == 0 or negative_count == len(list)

有更多的pythonic和/或正确的方法吗?首先要想到的是,一旦你有相反的迹象就停止迭代。

更新

到目前为止我喜欢这些答案,尽管我对表现感到疑惑。我不是一个表演迷,但我认为在处理列表时考虑性能是合理的。对于我的特定用例,我不认为这将是一个大问题,但为了完整这个问题,我认为解决它是好的。我的理解是min和max函数具有O(n)性能。到目前为止,两个建议的答案具有O(2n)性能,而一旦检测到相反的符号,我的上述例程添加短路退出将具有最差的O(n)性能。想法?

4 个答案:

答案 0 :(得分:18)

您可以使用all功能: -

>>> x = [1, 2, 3, 4, 5]

>>> all(item >= 0 for item in x) or all(item < 0 for item in x)
True

不知道这是否是最蟒蛇的方式。

答案 1 :(得分:14)

怎么样:

same_sign = not min(l) < 0 < max(l)

基本上,这会检查l的最小元素和最大元素是否跨越零。

这不会短路,但会避免Python循环。只有基准测试可以判断这是否是您数据的良好权衡(以及这件作品的性能是否重要)。

答案 2 :(得分:3)

而不是all你可以使用any,因为它也会在第一个真项上短路:

same = lambda s: any(i >= 0 for i in s) ^ any(i < 0 for i in s)

答案 3 :(得分:2)

与使用all类似,您可以使用any,它具有更好的性能,因为它会在第一次出现不同符号时中断循环:

def all_same_sign(lst):
    if lst[0] >= 0:
        return not any(i < 0 for i in lst)
    else:
        return not any(i >= 0 for i in lst)

如果你想考虑0,属于两个群体,那将会有点棘手:

def all_same_sign(lst):
    first = 0
    i = 0
    while first == 0:
        first = lst[i]
        i += 1
    if first > 0:
        return not any(i < 0 for i in lst)
    else:
        return not any(i > 0 for i in lst)

在任何情况下,您都会迭代列表一次而不是其他答案中的两次。您的代码具有在Python中迭代循环的缺点,这比使用内置函数效率低得多。