Уменьшить приращение значений массива до 1 - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь создать список (скажем, B), который увеличивается только тогда, когда есть разница в значениях другого списка (скажем, A), например:

[1,1,2,2,4,4] до [0,0,1,1,2,2] или

[1,1,1,1,4,4,4,4] до [0,0,0,0,1,1,1,1] и т. Д.

Следующий код делает это:

boxes=[1,1,1,1,4,4,4,4]
positions=[0]
position=0
for psn,box in list(enumerate(boxes))[:-1]:
    if boxes[psn+1]-box ==0:
        increment=0
    else:
        increment=1
    position=position+increment
    positions.append(position)
print(positions)

Кто-нибудь может дать предложения сделать это, используя списочные выражения (предпочтительно с использованием lambda функций)?

Ответы [ 5 ]

0 голосов
/ 09 января 2019

Метод с использованием zip и списочного понимания и нарезки

a = [1,1,2,2,4,4]
increments = [bool(i[1]-i[0]) for i in zip(a,a[1:])]
b = [sum(increments[:i]) for i in range(len(increments)+1)]
print(b) #prints [0, 0, 1, 1, 2, 2]

Объяснение: это решение, полагайтесь на это в Python:

любое число, отличное от 0 (или 0.0), оценивается как True при подаче на bool функцию

когда возникает такая необходимость * значения 1013 * и False превращаются в 1 и 0 соответственно

как работает sum функция: на самом деле что-то вроде sum([3,4]) означает вычисление 0+3+4, таким образом sum([True,True]) означает вычисление 0+True+True, что переводится в 0+1+1

0 голосов
/ 09 января 2019

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

В этом случае рекомендуется использовать itertools.groupby, numpy или простой цикл Python (как в вашем коде).

НО, если вы действительно хотите использовать понимание списка, одним из способов будет использование побочных эффектов.

Например:

boxes=[1,1,1,1,4,4,4,4]
positions = [0]
throwaway = [
    positions.append(positions[-1] + 0 if boxes[psn+1]-box == 0 else 1) 
    for psn, box in enumerate(boxes[:-1])
]
print(positions)
#[0, 0, 0, 0, 1, 1, 1, 1]

Вы используете понимание списка для создания списка с именем throwaway, но фактическое содержание throwaway вообще не полезно. Мы используем итерации для вызова append на positions. Поскольку append возвращает None, фактический результат понимания списка приведен ниже.

print(throwaway)
#[None, None, None, None, None, None, None]

Однако полагаться на подобные побочные эффекты не считается хорошей практикой.

0 голосов
/ 09 января 2019

Вот способ использования nummpy:

a = [1,1,2,2,4,4]
[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 1, 1, 2, 2]

Или для другого примера:

a = [1,1,1,1,4,4,4,4]
[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 0, 0, 1, 1, 1, 1]

Подробности

a = [1,1,2,2,4,4]

Получите первое различие массива с помощью np.diff

np.diff(a)
array([0, 1, 0, 2, 0]) 

И используйте np.clip, чтобы ограничить значения между 0 и 1:

np.clip(np.diff(a), 0, 1)
array([0, 1, 0, 1, 0])

Наконец, возьмите np.cumsum и добавьте 0 в начале, так как разница даст вам массив длины n-1:

[0] + np.cumsum(np.clip(np.diff(a), 0, 1)).tolist()
[0, 0, 1, 1, 2, 2]
0 голосов
/ 09 января 2019

Я вижу тупые решения, так что мы идем.

digitize

np.digitize(A, np.unique(A)) - 1
# array([0, 0, 0, 0, 1, 1, 1, 1])

factorize

import pandas 
pd.factorize(A)[0]
# array([0, 0, 0, 0, 1, 1, 1, 1])

groupby и ngroup

pd.Series(A).groupby(A).ngroup()

0    0
1    0
2    0
3    0
4    1
5    1
6    1
7    1
dtype: int64

unique

np.unique(A, return_inverse=True)[1]
# array([0, 0, 0, 0, 1, 1, 1, 1])

Использование понимания списка с itertools.accumulate:

from itertools import accumulate
from operator import add

list(accumulate([0] + [x != y for x, y in zip(A, A[1:])], add))
# [0, 0, 0, 0, 1, 1, 1, 1]
0 голосов
/ 09 января 2019

Использование itertools.groupby :

from itertools import groupby

a = [1,1,2,2,4,4]

result = [i for i, (_, group) in enumerate(groupby(a)) for _ in group]
print(result)

выход

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