Dadas dos listas de enteros, genere la lista más corta de pares donde cada valor en ambas listas esté presente. El primero de cada par debe ser un valor de la primera lista, y el segundo de cada par debe ser un valor de la segunda lista. El primero de cada par debe ser menor que el segundo del par.Lista de pares mínimos de un par de listas
Un simple zip
no funcionará si las listas son de diferentes longitudes, o si existe el mismo número entero en la misma posición en cada lista.
def gen_min_pairs(uplist, downlist):
for pair in zip(uplist, downlist):
yield pair
Aquí es lo que puedo llegar a hasta el momento:
def gen_min_pairs(uplist, downlist):
up_gen = iter(uplist)
down_gen = iter(downlist)
last_up = None
last_down = None
while True:
next_out = next(up_gen, last_up)
next_down = next(down_gen, last_down)
if (next_up == last_up and
next_down == last_down):
return
while not next_up < next_down:
next_down = next(down_gen, None)
if next_down is None:
return
yield next_up, next_down
last_up = next_up
last_down = next_down
Y aquí es una sencilla rutina de prueba:
if __name__ == '__main__':
from pprint import pprint
datalist = [
{
'up': [1,7,8],
'down': [6,7,13]
},
{
'up': [1,13,15,16],
'down': [6,7,15]
}
]
for dates in datalist:
min_pairs = [pair for pair in
gen_min_pairs(dates['up'], dates['down'])]
pprint(min_pairs)
El programa produce la salida de esperar que para el primer conjunto de fechas, pero falla para el segundo.
esperado:
[(1, 6), (7, 13), (8, 13)]
[(1, 6), (1, 7), (13, 15)]
real:
[(1, 6), (7, 13), (8, 13)]
[(1, 6), (13, 15)]
creo que esto se puede hacer mientras que sólo mirar a cada elemento de cada lista de una vez, por lo que en la complejidad O(len(up) + len(down))
. Creo que depende de los elementos numéricos exclusivos de cada lista.
EDITAR: Debería añadir que podemos esperar que estas listas se ordenen primero con el número entero más pequeño.
EDIT: uplist
y downlist
eran solo nombres arbitrarios. Los arbitrarios menos confusos pueden ser A
y B
.
Además, aquí es una más robusta rutina de prueba:
from random import uniform, sample
from pprint import pprint
def random_sorted_sample(maxsize=6, pop=31):
size = int(round(uniform(1,maxsize)))
li = sample(xrange(1,pop), size)
return sorted(li)
if __name__ == '__main__':
A = random_sorted_sample()
B = random_sorted_sample()
min_pairs = list(gen_min_pairs(A, B))
pprint(A)
pprint(B)
pprint(min_pairs)
Esto genera entradas realistas al azar, calcula la salida, y muestra las tres listas. He aquí un ejemplo de lo que produciría una implementación correcta:
[11, 13]
[1, 13, 28]
[(11, 13), (13, 28)]
[5, 15, 24, 25]
[3, 13, 21, 22]
[(5, 13), (15, 21), (15, 22)]
[3, 28]
[4, 6, 15, 16, 30]
[(3, 4), (3, 6), (3, 15), (3, 16), (28, 30)]
[2, 5, 20, 24, 26]
[8, 12, 16, 21, 23, 28]
[(2, 8), (5, 12), (5, 16), (20, 21), (20, 23), (24, 28), (26, 28)]
[3, 4, 5, 6, 7]
[1, 2]
[]
¿Qué desea que haga cuando usa (1,6) y va a 7, debería ser (7,13) o debería ser (7, Ninguno). –
¿Quiere decir para el primer conjunto de datos de prueba o el segundo?La salida para el primer conjunto de datos está bien; si el par '(7,13)' se reemplazara con el par '(1,7)' aún estaría bien. La salida para el segundo conjunto es incorrecta porque '7' no está presente en ningún par. El único par válido que podría contenerlo es '(1,7)'. 'Ninguno' nunca debería aparecer en un par. –
La segunda lista esperada parece violar los criterios. (13,15)? Donde esta el 16? – kevpie