2009-12-19 3 views
1

i ont une liste d'enregistrementsDe retour différents types de tableaux d'une expression lambda en F #

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

Je cherche à obtenir tourner ma liste d'enregistrements dans un tableau de valeurs comme [| « Red »; "vert", "bleu" |] ou [| 1; 2; 3 |]

Je peux sorta y arriver comme ça

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)) 

mais quand je l'appelle GetProp S itemList je retourner [| Taille 1; Taille 2; Taille 3 |]. Utile mais pas exactement ce que je cherche.

J'ai essayé la

suivante
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) 

mais il n'aime pas les deux types de retour différents.

Je suis ouvert à des suggestions sur les différentes façons (plus fonctionnelles?) De le faire et j'apprécierais votre contribution.

Répondre

5

Un type de variante personnalisé est en effet le chemin à parcourir ici (et généralement partout où vous avez besoin d'un type qui est "soit X ou Y"). Cependant, comme défini, votre fonction semble renvoyer un tableau dans lequel Color et Size sont mélangés, mais en pratique, il semble que vous ne souhaitiez que renvoyer l'un ou l'autre. Si oui, cela reflète le mieux les types:

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 |] 

Soit dit en passant, est-il une raison particulière pour laquelle vous utilisez pour tableau le type de retour ici, plutôt que la séquence habituelle paresseuse (seq)?

+0

le tableau est le type d'argument requis par la bibliothèque externe que j'utilise ensuite. Comment passer de la liste des enregistrements au seq de la valeur particulière? – RobRolls

+1

Toute liste est déjà un seq, tout comme n'importe quel tableau. En termes .NET, seq est 'IEnumerable '. Si vous avez besoin de faire un tableau ou une liste de n'importe quel seq aléatoire (et peut-être un paresseux), alors Seq.toArray et Seq.toList feront l'affaire. –

1

Go go gadget Array Compréhensions!

> [| 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"|] 

Vous n'avez pas besoin d'une structure de données ItemType ou ItemEnum intermédiaire.

+0

qui ne l'aider, comme il essaie d'écrire une fonction _single_ qui retourne des tableaux de _différente_ types d'éléments, en fonction sur ses arguments. –

4

Vous pouvez utiliser des modèles actifs pour voir vos données constituent quelques points de vue:

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;; 
+0

Je n'avais pas encore été exposé au modèle actif. Intéressant, merci. – RobRolls