2009-05-05 8 views
3

Prenons l'exemple suivant,La somme d'une propriété spécifique de tous les éléments dans une liste

J'ai une classe

public class SomeItem 
{ 
    public string Name; 
    public DateTime Published; 
    public uint16 Size; 
} 

J'ai un List<SomeItem> et je veux calculer la taille totale de tous les articles.
En C# Je voudrais simplement écrire

var totalSize = items.Sum((i) => i.Size); 

J'ai pris un coup d'œil à la liste des fonctions en F #, mais ils se plaignent toujours des types.

Comment écrivez-vous ceci en F #?

(j'ai essayé les moteurs de recherche, mais le soutien des moteurs de recherche pour F # est terrible)

Répondre

8

En supposant que vous avez une valeur de type IEnumerable<Item>, vous pouvez utiliser sum_by à partir du module Seq:

let totalSize = items |> Seq.sum_by (fun (i : Item) -> i.Size) 

Notez que le type d 'Microsoft.FSharp.Collections.List<T> F # est pas la même classe que celle que vous pourriez être utilisé à partir System.Collections.Generic.List<T>, et ils ne sont pas interchangeables. Toutefois, les méthodes dans le module Seq fonctionnent sur IEnumerable<T> et IEnumerable<T> est la même entre F # et C#.

+0

Vous venez d'écrire à peu près mot pour mot ce que j'écrivais. Il y a trop d'affiches ninja sur ce site. ;) – gradbot

+0

Hé, je ne suis pas sûr que je me compterais comme un ninja;). Je ne sais pas pourquoi cette réponse a été rejetée, cependant. –

+0

Je ne vois pas pourquoi vous avez été déprimé non plus. Merci pour la réponse – TimothyP

1

Ceci est « pliage » en F # et d'autres langages fonctionnels. Recherchez des exemples de Seq.fold.

+0

Les autres ont suggéré Seq.sum_by, Je suis intéressé pourquoi vous suggérer Seq.fold – TimothyP

+0

@TimothyP: Seq.fold ferait le travail, juste que son but est plus générique que sum_by (il pourrait multiplier toutes les valeurs dans une liste ensemble, par exemple). sum_by est la bonne solution simple dans ce cas. – Noldorin

+0

D'accord. Cependant, si vous cherchez des termes de recherche qui décrivent "faire des choses à tous les éléments d'une séquence et arriver à un résultat unique", alors la recherche de pliage/pliage vous donnera la solution générale. –

2
let totalSize = items |> List.sum_by (fun i -> i.Size) 

LINQ fonctionne très bien en fa # aussi, mais il est probablement préférable d'utiliser la compréhension de la liste comme ci-dessus, car il est plus dans la tradition fonctionnelle (et effectue aussi un peu plus rapide, car il n'utilise pas IEnumerable<T>).

+1

Ceci suppose que vous utilisez une F # 'List' d'ailleurs (c'est-à-dire une liste chaînée), plutôt que celle de System.Collections.Generic, que vous * éviterez * généralement dans F # (bien que F # ait aussi un alias pour il a appelé 'ResizeArray'). – Noldorin

+0

Eh bien, la liste vient d'une bibliothèque C#, donc c'est la liste System.Collections.Generic, mais vous m'avez fait, thnx – TimothyP

+0

Depuis que je fais cela sur une liste «normale», j'ai utilisé le Seq.sum_by – TimothyP

Questions connexes