Ленивый декартово произведение нескольких последовательностей (последовательность последовательностей)
Можете ли вы предложить более простой и понятный способ записи этой функции?
let cartesian_product sequences =
let step acc sequence = seq {
for x in acc do
for y in sequence do
yield Seq.append x [y] }
Seq.fold step (Seq.singleton Seq.empty) sequences
Ответы
Ответ 1
Менее элегантное, но (похоже,) быстрое решение:
let cartesian_product2 sequences =
let step acc sequence = seq {
for x in acc do
for y in sequence do
yield seq { yield! x ; yield y } }
Seq.fold step (Seq.singleton Seq.empty) sequences
;
> cartesian items |> Seq.length;;
Real: 00:00:00.405, CPU: 00:00:00.405, GC gen0: 37, gen1: 1, gen2: 0
val it : int = 1000000
> cartesian_product2 items |> Seq.length;;
Real: 00:00:00.228, CPU: 00:00:00.234, GC gen0: 18, gen1: 0, gen2: 0
val it : int = 1000000
Ответ 2
Я сравнил функцию Juliet, связанную с:
let items = List.init 6 (fun _ -> [0..9])
cart1 items |> Seq.length |> ignore
Реал: 00: 00: 03.324, CPU: 00: 00: 03.322, GC gen0: 80, gen1: 0, gen2: 0
и слегка измененной (чтобы сделать сравнение яблок с яблоками):
let cartesian items =
items |> Seq.fold (fun acc s ->
seq { for x in acc do for y in s do yield x @ [y] }) (Seq.singleton [])
cartesian items |> Seq.length |> ignore
Реал: 00: 00: 00.763, CPU: 00: 00: 00.780, GC gen0: 37, gen1: 2, gen2: 1
Ваш значительно быстрее (и вызывает меньше GC). Полагаю, что у вас хорошо.