2011-06-23 9 views
4

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

OK、SO "related"機能のおかげです。私はあなたがすべてのも、メンバーを確認することができthis questionを発見し、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 
+2

また、これは '[0,1,0,1,0]'は 'true'をです。私の提案: 'numpy.all(numpy.abs(numpy.diff(numpy.sign(a)))== 2)' –

3

であることは否定的であり、すべての奇数メンバーは、スライスを取ることによって、肯定的です1つ目の項目から始まり、または1つ目の項目から始まります。両方の可能性をカバーするために逆もテストしてください。

はそう:decimalモジュールとis_signed方法を使用して

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]))) 
+0

なぜ 'x> = 0'ではなく' x> 0'ですか? –

+0

それは本当に "交互符号"を定義する方法に依存します - 私は非負とゼロをグループ化するかどうかに応じてどちらかの方法を見ることができます(つまり、 "符号"を一般に負の符号で書くかどうかを判断する)独自のサインレスカテゴリ。 (そのような場合でも、[1,0,1,0]は「交互の兆候」であると主張する可能性もあります) – Brian

1

は:

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

私が好きなペアワイズは:iterableにはゼロが存在しない場合

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

これも動作します:

以下のような何かについて
def is_alternating_signs(iterable): 
    return all((x < 0) == (0 < y) for x, y in pairwise(iterable)) 
0

か...

def is_alternating_signs(aList): 
    return all((aList[i]^aList[i-1])<0 for i in range(1,len(aList))) 
0

何度とテスト、それをループでわずかストレートフォワードソリューションについてはどうですか?他の多くのソリューションの多くがリストを何度もループするので、おそらく最も速いです。

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

がここでおそらく他の提案のいくつかよりも効率が低い私のワンライナー、です:

def is_alternating_signs(lst): 
    return all(x * y < 0 for x, y in zip(lst, lst[1:])) 
関連する問題