Я уже давно борюсь с этим.Хотя у меня был какой-то длинный императивный метод, который работал, я решил изменить дизайн этой части:
- Взять список списков
Составить список первого элемента каждого подсписказатем снова первый элемент, но из последнего подсписка второй элемент, затем третий, пока этот последний список не будет исчерпан, проделайте то же самое для N-1 подсписка, который в основном дает своего рода произведение всех этих списков
Другими словами: [abc][FG][98]
следует оценивать как (примените функцию f
к каждому элементу, запятые предназначены для удобства чтения): [aF9, aF8, aG9, aG8, bF9, bF8, bG9, bG8, cF9,cF8, cG9, cG8]
Свести это и применить функцию к каждому элементу результата, которая сама возвращает список
- Эти списки затем сглаживаютсявернуть односвязный список
- Когда подсписок пуст (вызовите это E), тогда оцениваются только подсписки
0 .. E-1
(не в моем примере)
Вот рабочий примеркоторый ясно показывает его рекурсивный характер, но, очевидно, идет только как дВот три списка:
let rec nestedApply f inp =
match inp with
| [] -> []
| [x] -> x |> List.collect f
| [x;y] ->
x
|> List.collect (fun a -> y |> List.collect (fun b -> [a;b]))
|> List.collect f
| [x;y;z] ->
x
|> List.collect (fun a -> y |> List.collect (fun b -> z |> List.collect (fun c -> [a;b;c])))
|> List.collect f
| head::tail ->
// ??? I gave the following several attempts but couldn't get it right
nestedApply f tail
|> List.collect (fun a -> a::head)
|> List.collect f
Я бы предпочел решение, которое не взорвало стек.В конце концов мне понадобится lazy-eval, так что я, вероятно, прибегну к последовательностям, но со списками я думаю, что алгоритм будет проще думать.
Пример: nestedApply (fun a -> [a]) [[1 .. 5];[6;7];[11;12]]
Примерoutput:
[1; 6; 11; 1; 6; 12; 1; 7; 11; 1; 7; 12; 2; 6; 11; 2; 6; 12; 2; 7; 11; 2; 7;
12; 3; 6; 11; 3; 6; 12; 3; 7; 11; 3; 7; 12; 4; 6; 11; 4; 6; 12; 4; 7; 11; 4;
7; 12; 5; 6; 11; 5; 6; 12; 5; 7; 11; 5; 7; 12]
В качестве отступления, поскольку это выглядит довольно "нормальным" алгоритмом, хотя он не является декартовым произведением, к какому типичному общеизвестному алгоритму это относится ближе всего?