Python - 计算符号变化

时间:2010-05-29 22:42:54

标签: python list

我有一个从左到右阅读的数字列表。任何时候我在阅读序列时遇到符号更改我想要计算它。

X = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1] 
X = [-, +, +, -, +, -, +, +, -, -,-,+]

因此,在此列表中有8个符号更改。

当项目[0](在这种情况下为-3)为负时,它被视为符号更改。此外,列表中的任何0都被视为[-]

非常感谢任何帮助。

8 个答案:

答案 0 :(得分:13)

您可以使用itertools.groupby来计算正数和非正数的组:

>>> x = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1] 

>>> import itertools
>>> len(list(itertools.groupby(x, lambda x: x > 0)))

结果:

8

在你的问题中,你说出你想要的:

  • 计算更改,而不是组
  • 如果第一个元素不是正数,则计算额外的更改。

您可以通过直接测试第一个元素并调整结果来完成此操作:

>>> len(list(itertools.groupby(x, lambda x: x > 0))) - (x[0] > 0)

或者在进行分组之前在输入前加一个正数,然后从结果中减去1:

>>> len(list(itertools.groupby(itertools.chain([1], x), lambda x: x > 0))) - 1

注意你的输入列表是否可以为空 - 前一个解决方案会引发异常。

答案 1 :(得分:4)

X = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1]

last_sign = 1
sign_changes = 0

for x in X:
    if x == 0:
        sign = -1
    else:
        sign = x / abs(x)

    if sign == -last_sign:
        sign_changes = sign_changes + 1
        last_sign = sign

print sign_changes

答案 2 :(得分:1)

对于整数,(a^b) < 0如果 a b 的符号不同。

def countSignChanges(seq):
    # make sure 0's are treated as negative
    seq = [-1 if not x else x for x in seq]

    # zip with leading 1, so that opening negative value is 
    # treated as sign change
    return sum((a^b)<0 for a,b in zip([1]+seq, seq))


X = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1]
print countSignChanges(X)

给出了所需答案, 8

答案 3 :(得分:0)

numbers = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1]
# could be replaced by     signs = [x > 0 for x in numbers]
# but this methods gives us nice minus and plus signs
signs = map(lambda x: "+" if x > 0 else "-", numbers)

# zip(…) creates the pairs, each pair that has different signs
# adds one to "count"
count = sum(1 for x,y in zip(signs[:-1], signs[1:]) if x != y)

- &GT; 7

对于您的额外要求,列表开头的负数应视为另一项更改,只需在列表中添加一个正数。

如果您正在处理大型列表,请考虑使用生成器。 (izip,tee,...)

答案 4 :(得分:0)

这是一个使用折叠的解决方案,玩得很开心:

def lolwut((x,c), y):
    return (y, c+(x^y))

print reduce( lolwut ,(x > 0 for x in X), (True,0)) # 8
print reduce( lolwut ,(x > 0 for x in X), (False,0)) # 7

答案 5 :(得分:0)

如果您还没有被说服阅读itertools文档:

def pairs(iterable):
    'iter -> (iter0, iter1), (iter1, iter2), (iter3, iter4), ...'
    from itertools import izip, tee
    first, second = tee(iterable)
    second.next()
    return izip(first, second)

def sign_changes(l):
    result = 0
    if l and l[0]<=0: result += 1
    result += sum(1 for a,b in pairs(l) if b*a<=0 and (a!=0 or b!=0))
    return result

答案 6 :(得分:0)

这是一种没有循环的方法...对于大数据来说应该快得多;)(但是,由于numpy等,对于小型列表来说效率不高 - 而且对于小型列表来说效果会更好numpy数组比列表明显的原因 - 你甚至可以放弃转换......)

x = np.array([-3,2,7,-4,1,-1,1,6,-1,0,-2,1])
positive= x>0
count = np.logical_xor(positive[1:],positive[:-1]).sum()
count += not(positive[0])
print count

返回8

如果两个布尔值不同(从+到 - ),则Xor返回true并且非常快。代码有一个问题:如果某些东西从正号开始正好为0,那么它将被视为交叉。这正是您在问题中提出的问题,因为您将0表示为&#39; - &#39;。

答案 7 :(得分:0)

Input = [-1, 2, 3, -4, 5, -6, 7, 8, -9, 10, -11, 12] 

for i in range(len(Input)):
    if(Input[i]<1):
        Input[i]=0
    else:
        Input[i]=1

print(Input) #[0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]

count=0
check=Input[0]
for i in range(len(Input)-1):

    if check != Input[i + 1]:
        count+=1
        check=Input[i+1]


print(count) #9