Объединение 2 списков в F # - PullRequest
1 голос
/ 31 марта 2020

У меня есть 2 списка с координатами (по одному на ось), и я делаю из них квадраты:

// create all combinations
let squares = List<int * int * int * int>()
seqX
|> Seq.pairwise
|> Seq.iter (fun (x1, x2) ->
    seqY
    |> Seq.pairwise
    |> Seq.iter (fun (y1, y2) -> squares.Add(x1, y1, x2, y2))
)

Есть ли способ, используя функции сбора, чтобы сделать это? Я не могу использовать Seq.map, потому что вывод не будет соответствовать общему количеству итераций

|> Seq.map (fun (y1, y2) -> (x1, y1, x2, y2))

не будет работать

1 Ответ

5 голосов
/ 31 марта 2020

Вы можете использовать Seq.collect для отображения внутренней последовательности.

Collect (он же SelectMany в LINQ и flatMap в JS) проецирует каждый элемент на новую последовательность, и сглаживает результаты.

   seqX 
   |> Seq.pairwise 
   |> Seq.collect(fun (x1, x2) -> seqY |> Seq.map(fun (y1, y2) -> (x1, x2, y1, y2))

Или вы можете сделать выражение последовательности, чтобы сделать это для вас, что обесценивает вышеприведенное:

 seq {
    for (x1, x2) in seqX |> Seq.pairwise do
    for (y1, y2) in seqY |> Seq.pairwise do
    yield (x1, x2, y1, y2) 
 }

Выражения последовательности очень полезны, когда есть это глубина вовлечена. Это намного чище, чем писать вложенные замыкания для каждого уровня (seq |> Seq.collect (fun _ -> Seq.collect(fun...).

Вот пример, который находит все прямоугольные треугольники, стороны которых меньше 10, путем прохождения каждого возможного треугольника и проверки теоремы Пифагора .

 seq {
    let sides = [1..10]   
    for a in sides do
    for b in sides do
    for c in sides do
    if a * a + b * b = c * c then
        yield (a, b, c) 
 }

Это было бы намного более уродливым обезвоживанием.

...