Учитывая два списка целых чисел, сгенерируйте кратчайший список пар, где присутствует каждое значение в обоих списках. Первая из каждой пары должна быть значением из первого списка, а вторая из каждой пары должна быть значением из второго списка. Первая из каждой пары должна быть меньше второй пары.Список минимальных пар из пары списков
Простой zip
не будет работать, если списки имеют разную длину или если одно и то же целое число существует в одной позиции в каждом списке.
def gen_min_pairs(uplist, downlist):
for pair in zip(uplist, downlist):
yield pair
Вот что я могу придумать до сих пор:
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
А вот простой тест рутина:
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)
Программа производит ожидать выхода первого набора дат, но не второй.
Ожидаемое:
[(1, 6), (7, 13), (8, 13)]
[(1, 6), (1, 7), (13, 15)]
Actual:
[(1, 6), (7, 13), (8, 13)]
[(1, 6), (13, 15)]
Я думаю, что это можно сделать, только глядя на каждый элемент каждого списка один раз, так что в сложности O(len(up) + len(down))
. Я думаю, это зависит от числа элементов, уникальных для каждого списка.
EDIT: Я должен добавить, что мы можем ожидать, что эти списки будут отсортированы с наименьшим целым первым.
EDIT: uplist
и downlist
были просто произвольными именами. Меньше путающих произвольных могут быть A
и B
.
Кроме того, здесь более надежный тест рутина:
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)
Это генерирует случайные реалистичные входы, вычисляет выход, и отображает все три списка. Вот пример того, что правильная реализация будет производить:
[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]
[]
Что вы хотите, чтобы использовать, когда оно использует (1,6), и идет до 7, если оно (7,13) или должно быть (7, None). – 2010-11-29 15:09:23
Вы имеете в виду первый набор тестовых данных или второй?Вывод для первого набора данных в порядке; если пара `(7,13)` была заменена на пару `(1,7)`, все равно было бы хорошо. Результат для второго набора неверен, потому что `7` не присутствует ни в одной паре. Единственная допустимая пара, которая может содержать это, - `(1,7)`. `None` никогда не должен появляться в паре. – 2010-11-29 15:17:43
Второй ожидаемый список, похоже, нарушает критерии. (13,15)? Где 16? – kevpie 2010-11-29 15:26:49