Question

Est-il possible de résumer des données hiérarchiques LINQ de .NET?

Ma classe de données ressemble à ceci:

class Node
{
    public decimal Amount;
    public IEnumerable<Node> Children { get; set; }
}

J'aurais certaines données ressemble à cela, mais l'arbre pourrait bien sûr être arbitrairement profond.

var amounts = new Node
{
    Amount = 10;
    Children = new[]
    {
        new Node
        {
            Amount = 20
        },
        new Node
        {
            Amount = 30
        }
    }
};

Il est possible somme tous les montants et obtenir le résultat 60 avec une simple requête LINQ?

Était-ce utile?

La solution

pouvez écrire des expressions lambda récursives , mais vous devez être fou ou incroyablement lumineux pour essayer (je ne l'ai pas compris que). Mais vous pouvez tricher:

    Func<Node, decimal> nodeSum = null;
    nodeSum = node => {
        decimal result = node.Amount;
        if (node.Children != null) {
            result = result + node.Children.Sum(nodeSum);
        }
        return result;
    };
    var value = nodeSum(amounts);

Autres conseils

Vous pouvez le faire avec une fonction d'ordre supérieur:

Func<Node, decimal> summer = null;
summer = node => node.Amount + 
                 (node.Children == null ? 0m : node.Children.Sum(summer));
decimal total = summer(amounts);

Notez que si vous pouvez vous assurer que node.Children ne sera jamais nulle, l'été peut être plus simple:

summer = node => node.Amount + node.Children.Sum(summer);

Vous pouvez utiliser l'opérateur coalescent null:

summer = node => node.Amount + 
                 (node.Children ?? Enumerable.Empty<Node>()).Sum(summer);

Bien sûr, vous pouvez mettre cela en une méthode distincte au lieu:

static decimal SumNodes(Node node)
{
    return node.Amount + 
        (node.Children ?? Enumerable.Empty<Node>())
            .Sum((Func<Node, decimal>)SumNodes);
}

Notez la laideur ici est due à une ambiguïté dans les conversions de groupe de méthode. groupes de méthode ne reçoivent pas beaucoup d'amour dans l'inférence de type.

puis appelez SumNodes(amount). Beaucoup d'options:)

Exemple complet de la première forme:

using System;
using System.Collections.Generic;
using System.Linq;

class Node
{
    public decimal Amount;
    public IEnumerable<Node> Children { get; set; }
}

public class Test
{
    static void Main()
    {
        var amounts = new Node {
            Amount = 10, Children = new[] {
                new Node { Amount = 20 },
                new Node { Amount = 30 }
            }
        };

        Func<Node, decimal> summer = null;
        summer = node => node.Amount + 
            (node.Children == null ? 0m : node.Children.Sum(summer));

        decimal total = summer(amounts);

        Console.WriteLine(total);
    }
}

Je ne suis pas sûr que je dirais l'un de ces un « simple » requête LINQ, l'esprit que vous ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top