A menudo me encuentro con la necesidad de dividir una secuencia en dos subsecuencias de elementos que satisfacen y no satisfacen un predicado dado (preservando el orden relativo original).¿Cómo dividir una secuencia de acuerdo con un predicado?
Esta función hipotética "splitter" sería algo como esto en acción:
>>> data = map(str, range(14))
>>> pred = lambda i: int(i) % 3 == 2
>>> splitter(data, pred)
[('2', '5', '8', '11'), ('0', '1', '3', '4', '6', '7', '9', '10', '12', '13')]
Mi pregunta es:
qué Python ya tienen una forma estándar/incorporado para hacer esto?
Esta funcionalidad no es ciertamente difícil de codificar (ver Apéndice a continuación), pero por una serie de razones, preferiría usar un método estándar/integrado que uno auto rodado.
Gracias!
Adición:
La mejor función estándar que he encontrado hasta el momento para el manejo de esta tarea en Python es itertools.groupby
. Para utilizarlo para sin embargo esta tarea particular, es necesario llamar a la función de predicado dos veces para cada miembro de la lista, que me parece molesto tonta:
>>> import itertools as it
>>> [tuple(v[1]) for v in it.groupby(sorted(data, key=pred), key=pred)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
(La última salida anterior difiere de la deseada se mostró anteriormente en ese la subsecuencia de elementos que satisfacen el predicado viene en último lugar en vez de primero, pero esto es muy leve y muy fácil de corregir si es necesario.)
Se pueden evitar las llamadas redundantes al predicado (haciendo, básicamente, un " memoria en línea "), pero mi mejor intento de esto se vuelve bastante elaborado, muy lejos de la simplicidad de splitter(data, pred)
:
>>> first = lambda t: t[0]
>>> [zip(*i[1])[1] for i in it.groupby(sorted(((pred(x), x) for x in data),
... key=first), key=first)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
Por cierto, si no se preocupan por preservar el orden original, orden predeterminado sorted
's hace el trabajo (por lo que el parámetro key
puede omitirse de la llamada sorted
):
>>> [zip(*i[1])[1] for i in it.groupby(sorted(((pred(x), x) for x in data)),
... key=first)]
[('0', '1', '3', '4', '6', '7', '9', '10', '12', '13'), ('2', '5', '8', '11')]
¿Puede usted ayudarnos a entender por qué usted no desea escribir una función? –
posible duplicado de [Python: ¿dividir una lista basada en una condición?] (Http://stackoverflow.com/questions/949098/python-split-a-list-based-on-a-condition) – user