3

我做了一个小函数,给定一个元组,比较这个元组中的所有元素是否具有相同的符号。

例如,tuple =[-1, -4, -6, -8]是好的,while[-1, -4, 12, -8]是坏的。我不确定我是否做出了最聪明的实施,所以我知道这是要问的地方。

def check_consistent_categories(queryset):
    try:
        first_item = queryset[0].amount

        if first_item < 0:
            for item in queryset:
                if item > 0:
                    return False
            return True
        else:
            for item in queryset:
                if item < 0:
                    return False
            return True
    except:
        return False
4

9 回答 9

14

这可能会帮助您:

def all_same_sign(ints):
    return all(x < 0 for x in ints) or all(x > 0 for x in ints)

您可能需要将 < 和 > 更改为 <= 和 >=,具体取决于您要如何处理 0。

于 2010-12-29T22:16:49.807 回答
3

在@EOL 的解决方案之后,但无需列表索引或多次迭代即可工作。

def all_same_sign(sequence):
    items = iter(sequence)
    try:
        first = items.next() > 0
    except StopIteration:
        return True
    return all((item > 0) == first for item in items)

这也发生在我身上,但没有利用所有/任何短路:

def all_same_sign(sequence):
    return len(set(item > 0 for item in sequence)) <= 1
于 2010-12-29T23:25:56.280 回答
1

这是一个很好的pythonic方式(使用all()):

from math import copysign

sign = lambda x: copysign(1, x)  # Sign function

def check_consistent_categories(sequence):
    main_sign = sign(sequence[0])
    return all(sign(y) == main_sign for y in sequence)

(对于 Python 2.6+,它引入了该math.copysign()函数)。该解决方案认为 0 为正。

不过,Mark Byers 的解决方案更灵活,也可以说更易读。

于 2010-12-29T22:19:27.170 回答
1

只是一个不相关的 nit,因为您正在这样做:

try:
    [...]
except:
    [...]

您忽略all了异常,我的朋友要非常小心,这将隐藏很多错误,而在进行异常处理时始终保持精确,例如:

try:
    [...]
except IndexError:
    # Handle out of index
except IOError:
    # Handle I/O error

等等。在编写更大的 python 应用程序时请记住这一点。

于 2010-12-29T22:26:04.903 回答
1

为什么不利用这样一个事实,即如果所有数字都是相同的符号,那么每个单独数字的绝对值之和将等于每个数字之和的绝对值?

def check_sign(queryset):
    return abs(sum(queryset)) == sum(map(abs, queryset))

显示数学细节的示例

案例1:所有数字都具有相同的符号

a = (-1, -4, -8)
sum(a) = -13
abs(sum(a)) = 13        # the absolute value of the tuple's sum
map(abs, a) = [1, 4, 8]
sum(map(abs, a)) = 13   # the tuple's sum of each element's absolute value

两种方法都产生 13,因此符号相同。

案例2:并非所有数字都具有相同的符号

b = (-1, 4, 8)
sum(b) = 11
abs(sum(b)) = 11        # the absolute value of the tuple's sum 
map(abs, b) = [1, 4, 8]
sum(map(abs, b)) = 13   # the tuple's sum of each element's absolute value

这些方法产生不同的数字(11 和 13),因此符号并不完全相同。

于 2010-12-29T22:53:06.883 回答
1

这是一个也适用于生成器等的工具

def all_same_sign(ints):
    ints = iter(ints)
    first_is_positive = next(ints) > 0
    return all( (x>0) == first_is_positive for x in ints)

如果ints为空,则会收到 StopIteration 异常。

此版本将 0 与负数组合在一起。>=如果您希望使用正数进行分组,请使用

于 2010-12-30T06:53:09.327 回答
1
def all_same_sign(iterable):
    # Works with any iterable producing any items that can be compared to zero.
    # Iterates through the input no more than once, and this fact is immediately
    # obvious from the code.
    # Exits as soon as a bad combination has been detected.
    pos = neg = zero = False
    for item in iterable:
        if item > 0:
            pos = True
        elif item < 0:
            neg = True
        else:
            zero = True
        # Adjust the following statement if a different
        # treatment of zero is required.
        # Redundant parentheses added for clarity.
        if (pos and neg) or zero:
            return False
    return True
于 2011-01-01T02:36:52.477 回答
0

如果您的数字已排序,您只需要比较两端。如果没有,您可以对它们进行排序:

def same_sign(numbers):
    numbers = sorted(numbers)
    #if numbers[0]==0: return True                Uncomment if you consider 0 positive
    if numbers[0]*numbers[-1]>0: return True
    return False

如果您将其更改>=0为零,则将被视为符号中性。我不确定这是否比当前答案更好,但对于大型数据集可能会更快。

于 2010-12-29T22:51:15.643 回答
0

使用乘以你的数字的原则,如果它们都相同,则为正,否则为负,

import operator

def all_same_sign(intlist):
    return reduce(operator.mul, intlist) > 0

>>> all_same_sign([-1, -4, -6, -8])
True
>>> all_same_sign([-1, -4, 12, -8])
False

虽然这不处理零...

于 2010-12-31T17:05:38.993 回答