8
votes

Utilisation de LINQ pour obtenir la somme / la moyenne d'une liste avec des objets personnalisés

J'ai une classe: xxx

donné une liste , comment obtenir la moyenne de celui-ci à l'aide de LINQ? Un pour équivalent en boucle sera quelque chose comme ceci: xxx

Vous pouvez utiliser n'importe quelle fonction linq intégrée uniquement. Vous ne pouvez pas définir une extension qui prend soin de cette fonction.

aucune idée?

EDIT: Bien sûr, vous pouvez utiliser deux distincts Méthode d'extension à la somme pour X et Y Composant avant de les fusionner. Mais ce n'est pas ce que je veux. Ce que je veux, c'est une seule requête / méthode qui fait le travail


3 commentaires

Deux sommes-elles ne fonctionnent pas? Quelque chose comme ptlist.sum (p => p.x); et ptlist.sum (p => p.y);


"Comment obtenir la moyenne de celui-ci à l'aide de Linq?" .. je pense que vous voulez dire la somme


@Le_ajp: Cela peut fonctionner, mais je veux tout mettre dans une requête, c'est juste ça.


3 Réponses :


6
votes

Vous devrez utiliser la méthode AGRANGATE à la place afin que vous puissiez fournir votre propre fonction d'agrégation ( somme est juste un cas spécialisé spécifique de cette méthode). Quelque chose comme: xxx

Je sais que vous dites que vous ne voulez pas de méthodes supplémentaires définies, mais s'il s'agit d'une opération courante, je serais enclin à écrire une méthode d'extension pour cela, c'est-à-dire < / p> xxx

car il est beaucoup plus lisible pour pouvoir écrire: xxx


2 commentaires

S'il a déjà surchargé les opérateurs pour pointed , il n'est pas nécessaire de redéfinir l'addition.


Pourriez-vous expliquer le but du nouveau point de pointe (0, 0), ?



13
votes

La fonction agrégat code> serait utile ici.

var sum = list.Aggregate((acc, cur) => acc + cur);
var average = list.Aggregate((acc, cur) => acc + cur) / list.Count;


3 commentaires

Poind est un type de référence, donc en fonction de la manière dont les opérateurs sont implémentés, vous pouvez très bien obtenir une erreur d'argumentation ou de NullReferenceException ici. Éventuellement utile de fournir une graine non nulle à l'accumulateur.


C'est un bon, mais je ne comprends pas bien pourquoi je ne pouvais pas penser. Duh !!


@Greg heech: c'est un point juste. J'ai automatiquement supposé qu'il s'agissait d'un struct (comme le point type WPF / System.Drawing) est, mais il semble qu'il l'a défini comme une classe. @Gngu bientôt Hui: Je vous recommande de définir votre type pointe sous forme de struct , sauf si vous avez une bonne raison autrement. Agrégats utilisera ensuite par défaut (pointeur) comme la graine, ce qui signifie que les choses vont bien fonctionner.



0
votes
    [Fact]
    public void CanAddManyPointDs()
    {
        var points = new[]{
            new PointD( 1,1),
            new PointD( 2,3),
            new PointD( 3,4),
        };

        var result = points.Aggregate((p1, p2) => new PointD(p1.X + p2.X, p1.Y + p2.Y));
        Assert.Equal(result.X,6);
        Assert.Equal(result.Y,8);
    }

0 commentaires