Python - подсчет изменений знака - PullRequest
4 голосов
/ 30 мая 2010

У меня есть список номеров, которые я читаю слева направо. Каждый раз, когда я сталкиваюсь с изменением знака при чтении последовательности, я хочу считать ее.

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

Итак, в этом списке 8 изменений знака.

Когда Элемент [0] (в данном случае -3) отрицателен, это считается изменением знака. Также любой 0 в списке считается [-].

Любая помощь будет принята с благодарностью.

Ответы [ 7 ]

13 голосов
/ 30 мая 2010

Вы можете использовать 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

Остерегайтесь, если ваш список ввода может быть пустым - прежнее решение вызовет исключение.

4 голосов
/ 30 мая 2010
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
1 голос
/ 12 марта 2011

Для целых чисел, (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 .

0 голосов
/ 16 сентября 2016

Вот способ сделать это без циклов ... Это должно быть намного быстрее для больших данных;) (однако, из-за большого количества символов и т. Д., Это будет не так эффективно для небольших списков - и это будет намного лучше для массив 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 как '-'.

0 голосов
/ 30 мая 2010

Если вас еще не убедили прочитать документацию 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
0 голосов
/ 30 мая 2010

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

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
0 голосов
/ 30 мая 2010
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)

-> 7

Для вашего дополнительного требования, чтобы отрицательное число в начале списка считалось другим изменением, просто добавьте положительное число в ваш список.

Если вы имеете дело с огромными списками, подумайте об использовании генераторов. (изип, тройник,…)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...