我有一个从左到右阅读的数字列表。任何时候我在阅读序列时遇到符号更改我想要计算它。
X = [-3,2,7,-4,1,-1,1,6,-1,0,-2,1]
X = [-, +, +, -, +, -, +, +, -, -,-,+]
因此,在此列表中有8个符号更改。
当项目[0]
(在这种情况下为-3)为负时,它被视为符号更改。此外,列表中的任何0都被视为[-]
。
非常感谢任何帮助。
答案 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