Обнаружить знаковые признаки - PullRequest
4 голосов
/ 23 июня 2011

Есть ли хороший и короткий способ узнать, содержит ли список Python (или массив numpy) числа с чередующимися знаками?Другими словами:

is_alternating_signs([1, -1, 1, -1, 1]) == True
is_alternating_signs([-1, 1, -1, 1, -1]) == True
is_alternating_signs([1, -1, 1, -1, -1]) == False

Ответы [ 7 ]

7 голосов
/ 23 июня 2011

ОК, благодаря SO "связанной" функции. Я нашел этот вопрос и принял ответ ianalis и комментарий lazyr

def is_alternating_signs(a):
    return numpy.all(numpy.abs(numpy.diff(numpy.sign(a))) == 2)



print is_alternating_signs([1, -1, 1, -1, 1]) 
print is_alternating_signs([-1, 1, -1, 1, -1]) 
print is_alternating_signs([1, -1, 1, -1, -1]) 

Выход

True
True
False
3 голосов
/ 23 июня 2011

Вы можете проверить, что каждый четный член отрицателен, а каждый нечетный член положителен, взяв срез каждого второго элемента, начиная либо с начала, либо с первой позиции.Также проверьте обратное, чтобы охватить обе возможности.

так:

def is_alternating_signs(l):
    return ( (all(x<0 for x in l[::2]) and all(x>=0 for x in l[1::2])) or
             (all(x>=0 for x in l[::2]) and all(x<0 for x in l[1::2])))
1 голос
/ 23 июня 2011

Использование десятичного модуля и is_signed метод:

from decimal import Decimal

a = [1, -1, 1, -1, 1]
b = [-1, 1, -1, 1, -1]
c = [1, -1, 1, -1, -1]

def is_alternating_signs(values):
    lVals = [Decimal(val).is_signed() for val in values]
    prevVal = lVals.pop(0)
    for val in lVals:
        if prevVal == val:
            return False
        prevVal = val
    return True

is_alternating_signs(a)
is_alternating_signs(b)
is_alternating_signs(c)
0 голосов
/ 24 июня 2011

Вот мой однострочный текст, который, вероятно, менее эффективен, чем некоторые другие предложения:

def is_alternating_signs(lst):
    return all(x * y < 0 for x, y in zip(lst, lst[1:]))
0 голосов
/ 23 июня 2011

А как насчет простого решения: выполнить его один раз и протестировать? Возможно, самый быстрый, потому что многие другие решения повторяют список несколько раз.

def signs_are_alternating(numbers):
    """Return True if numbers in given list have alternating signs, False
    otherwise. If given list has less than 2 elements, return False.

    >>> signs_are_alternating([1, -1, 1, -1, 1])
    True
    >>> signs_are_alternating([-1, 1, -1, 1, -1])
    True
    >>> signs_are_alternating([1, -1, 1, -1, -1])
    False

    """
    if len(numbers) < 2:
        return False
    previous_positive = (numbers[0] < 0)  # Pretend it starts alternating
    for number in numbers:
        this_positive = (number >= 0)
        if previous_positive == this_positive:
            return False
        previous_positive = this_positive
    return True

Обратите внимание, что я не совсем уверен, каково предполагаемое поведение, если список ввода содержит менее 2 элементов.

0 голосов
/ 23 июня 2011

как насчет чего-то вроде ...

def is_alternating_signs(aList):
    return all( (aList[i]^aList[i-1])<0 for i in range(1,len(aList)) )
0 голосов
/ 23 июня 2011

Мне нравится попарно:

from itertools import izip, tee

def pairwise(iterable):
    a, b = tee(iterable)
    next(b)
    return izip(a, b)

def is_alternating_signs(iterable):
    return all(x < 0 < y or x > 0 > y for x, y in pairwise(iterable))

Если в * 1004 нет нулей, это также работает:

def is_alternating_signs(iterable):
    return all((x < 0) == (0 < y) for x, y in pairwise(iterable))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...