Вычисление декартового произведения из списка чисел с помощью F # - PullRequest
6 голосов
/ 01 июня 2009

Я новичок в F #

Я пытаюсь вычислить декартовы произведения из списка чисел. Я "позаимствовал" это.

let xs = [1..99]
let ys = [1..99]
seq {for x in xs do for y in ys do yield x * y}

Есть ли лучший или более элегантный способ?

Gary

Ответы [ 3 ]

9 голосов
/ 01 июня 2009

Другой вариант решения проблемы на основе функциональности модуля List:

let xs = [1..99]
let ys = [1..99]
let zs = xs |> List.collect (fun x -> ys |> List.map (fun y -> x*y))

, который исключает дополнительные вызовы .concat и должен также выполнять эту работу.

Но я бы придерживался вашего решения. Это должен быть самый читаемый, который является реальным победителем матча. (Просто попробуйте прочитать вслух коды. Ваш совершенно понятен, а нолдорины или мои нет.)

7 голосов
/ 02 июня 2009

Отказ от ответственности: у меня нет машины с установленным текущим F #, поэтому я не могу проверить свой код. Тем не менее, если вы украли sequence из Haskell, вы можете написать свою программу как

let cartesian = sequence >> List.map product

и запустите его как

cartesian [[1..99]; [1..99]]

Вот как написать sequence. Это обобщенная версия выражения последовательности, которое вы написали. Он просто обрабатывает неограниченное количество списков: { for x in xs do for y in ys do for z in zs ... yield [x;y;z;...] }.

let rec sequence = function
  | [] -> Seq.singleton []
  | (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
// also you'll need product to do the multiplication
let product = Seq.fold_left1 ( * )

Тогда вы можете написать свою программу как

let cartesian xs ys = [xs; ys] |> sequence |> List.map product
// ... or one-argument, point-free style:
let cartesian' = sequence >> Seq.map product

Возможно, вам придется изменить Seq с на List с.

Однако число людей, которые могут угадать значение вашего необщего понимания списка, вероятно, намного больше, чем распознает имя sequence, так что вам, вероятно, лучше с пониманием списка. sequence пригодится в любое время, когда вы захотите запустить целый список выражений вычислений.

2 голосов
/ 01 июня 2009

Действительно, есть немного более элегантный способ (по крайней мере, в функциональном смысле) для вычисления декартовых произведений, который использует функции, существующие в классе List. (Нет необходимости включать последовательности или циклы, по крайней мере, напрямую.)

Попробуйте это:

let xs = [1..99]
let ys = [1..99]
xs |> List.map(fun x -> ys |> List.map(fun y -> x * y)) |> List.concat

Чуть дольше, хотя, по-видимому, более функционально по стилю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...