Tengo esta lista:

myList = [a, a, a, b, b, a, c, c, b, a]

Quiero contar la entrada y la salida de cada artículo único.

Entrada para 'a' = número de apariciones = 5 (cuando una transición ENTRA en 'a')

Salida para 'a' = número de caracteres diferentes después de 'a' = 2 (cuando una transición SALE de 'a' a otro carácter)

Para la entrada tengo esto y funciona:

myListDict = {}    
for item in myList:
    myListDict.setdefault(item, 0)
    myListDict[item] += 1

Pero realmente no sé cómo hacer esto de una manera rápida y elegante para el flujo de salida, en una sola iteración general, si es posible.

4
Marko 14 sep. 2018 a las 14:27

3 respuestas

La mejor respuesta

Si desea calcular tanto la entrada como la salida en una sola pasada, puede usar esta estructura:

from collections import Counter

last_char = None

my_list = "aaabbaccba"

inflow = Counter()
outflow = Counter()

for char in my_list:
    inflow[char] += 1
    if last_char and char != last_char:
        outflow[last_char] += 1
    last_char = char


print(inflow)
print(outflow)

Emite:

Counter({'a': 5, 'b': 3, 'c': 2})
Counter({'a': 2, 'b': 2, 'c': 1})

Tenga en cuenta que con Counter, usted no ' No es necesario setdefault.

1
Eric Duminil 14 sep. 2018 a las 11:51

Usando collections.Counter y itertools.groupby:

from collections import Counter
from itertools import groupby

def in_out_flow(lst):
    in_flow = Counter(lst)
    out_flow = Counter(k for k, _ in groupby(lst))
    out_flow[lst[-1]] -= 1
    for k,v in in_flow.items():
      print('key: {}, in flow: {}, out flow: {}'.format(k, v, out_flow[k]))

Ejemplos:

in_out_flow(['a', 'a', 'a', 'b', 'b', 'a', 'c', 'c', 'b', 'a'])
print('##')
in_out_flow(['a', 'a', 'a', 'b', 'a', 'c', 'a', 'b'])

Salidas:

key: a, in flow: 5, out flow: 2
key: b, in flow: 3, out flow: 2
key: c, in flow: 2, out flow: 1
##
key: a, in flow: 5, out flow: 3
key: b, in flow: 2, out flow: 1
key: c, in flow: 1, out flow: 1
1
Chris_Rands 14 sep. 2018 a las 11:52

Uso itertools.groupby para eliminar elementos sucesivos idénticos, luego cuento las transiciones de entrada. Para el flujo de salida, solo tenemos que restar 1 al recuento de entrada para el último elemento de la lista.

from itertools import groupby
from collections import Counter

myList = ['a', 'a', 'a', 'b', 'b', 'a', 'c', 'c', 'b', 'a']

uniques = [key for key, g in groupby(myList)]  # ['a', 'b', 'a', 'c', 'b', 'a']
c = Counter(uniques)
inflow = dict(c)
c.update({myList[-1]: -1})  # No outflow for the last element
outflow = dict(c)

print(inflow)
# {'a': 3, 'b': 2, 'c': 1}

print(outflow)
# {'a': 2, 'b': 2, 'c': 1}
1
Thierry Lathuille 14 sep. 2018 a las 12:18