Как прокомментировал Рекс, если вы хотите это только для двух случаев, то у вас, вероятно, не возникнет никаких проблем, если вы оставите код как есть. Однако, если вы хотите извлечь общий шаблон, вы можете написать функцию, которая разбивает список на подсписок заданной длины (2 или 3 или любое другое число). После этого вы будете использовать map
, чтобы превратить каждый список указанной длины в Vector
.
Функция разделения списка недоступна в библиотеке F # (насколько я могу судить), поэтому вам придется реализовать ее самостоятельно. Это можно сделать примерно так:
let divideList n list =
// 'acc' - accumulates the resulting sub-lists (reversed order)
// 'tmp' - stores values of the current sub-list (reversed order)
// 'c' - the length of 'tmp' so far
// 'list' - the remaining elements to process
let rec divideListAux acc tmp c list =
match list with
| x::xs when c = n - 1 ->
// we're adding last element to 'tmp',
// so we reverse it and add it to accumulator
divideListAux ((List.rev (x::tmp))::acc) [] 0 xs
| x::xs ->
// add one more value to 'tmp'
divideListAux acc (x::tmp) (c+1) xs
| [] when c = 0 -> List.rev acc // no more elements and empty 'tmp'
| _ -> failwithf "not multiple of %d" n // non-empty 'tmp'
divideListAux [] [] 0 list
Теперь вы можете использовать эту функцию для реализации двух ваших преобразований следующим образом:
seq { for [x; y] in floatList |> divideList 2 -> Vector2(x,y) }
seq { for [x; y; z] in floatList |> divideList 3 -> Vector3(x,y,z) }
Это выдаст предупреждение, потому что мы используем неполный шаблон, который ожидает, что возвращаемые списки будут иметь длину 2 или 3 соответственно, но это правильное ожидание, поэтому код будет работать нормально. Я также использую краткую версию выражения последовательности ->
делает то же самое, что и do yield
, но его можно использовать только в простых случаях, подобных этому.