Возвращает различные типы массивов из лямбда-выражения в F#

StackOverflow https://stackoverflow.com/questions/1932124

Вопрос

у меня есть список записей

type Item = { Color : string; Size : int}
let itemList = [{Color="Red"; Size=1};
                {Color="Green"; Size=2};
                {Color="Blue"; Size=3};]

Я хочу превратить свой список записей в массив значений типа [|"Красный"; "Зеленый"; "Синий" |] или [|1; 2; 3|]

Я могу вроде как добраться туда вот так

type ItemType =
| Color of string
| Size of int

type ItemEnum =
| C
| S

let GetProp x y =
match x with
| C -> List.toArray y |> Array.map(fun x -> ItemType.Color(x.Color))
| S -> List.toArray y |> Array.map(fun x -> ItemType.Size(x.Size))

но когда я звоню GetProp S itemList Я возвращаюсь [| Размер 1;Размер 2;Размер 3|].Полезно, но не совсем то, что я ищу.

Я пробовал следующее

let GetProp2 x y : 'a[] =
match x with
| Color -> List.toArray y |> Array.map(fun x -> x.Color)
| Size -> List.toArray y |> Array.map(fun x -> x.Size)

но ему не нравятся два разных типа возвращаемых данных.

Я открыт для предложений по различным (более функциональным?) способам сделать это и был бы признателен за ваш вклад.

Это было полезно?

Решение

Пользовательский тип варианта - это действительно правильный путь здесь (и, как правило, везде, где вам нужен тип "либо X, либо Y").Однако, как определено, ваша функция выглядит так, как будто она может возвращать массив, в котором Color и Size они смешаны, но на практике кажется, что вы хотите, чтобы он возвращал только одно или другое.Если это так, то это лучше всего отражено в типах:

type Items =
| Colors of string[]
| Sizes of int[]

let GetProp x ys =
match x with
| C -> Colors [| for y in ys -> y.Color |]
| S -> Sizes [| for y in ys -> y.Size |]

Кстати, есть ли какая-то конкретная причина, по которой вы используете array для возвращаемого типа здесь, а не обычную ленивую последовательность (seq)?

Другие советы

Вы можете использовать активные шаблоны, чтобы просмотреть ваши данные с нескольких точек зрения:

let (|AsColor|) (v: Item list) = [| for i in v -> i.Color |];;

let (|AsSize|) (v: Item list) = [| for i in v -> i.Size |];;

match itemList,itemList with
  |AsColor ca, AsSize sa -> printfn "%A; %A" ca sa;;

Вперед, к пониманию массива гаджетов!

> [| for a in itemList do yield a.Size |];;
val it : int [] = [|1; 2; 3|]
> [| for a in itemList do yield a.Color |];;
val it : string [] = [|"Red"; "Green"; "Blue"|]

Вам не нужен посредник ItemType или ItemEnum структура данных.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top