Domanda

Ho un ciclo come il seguente, posso fare lo stesso utilizzando SUM multipla?

foreach (var detail in ArticleLedgerEntries.Where(pd => pd.LedgerEntryType == LedgerEntryTypeTypes.Unload &&
                                                                pd.InventoryType == InventoryTypes.Finished))
{
     weight += detail.GrossWeight;
     length += detail.Length;
     items  += detail.NrDistaff;
}
È stato utile?

Soluzione

Tecnicamente parlando, quello che hai è probabilmente il modo più efficace per fare quello che chiedete. Tuttavia, è possibile creare un metodo di estensione sul IEnumerable chiamato Ciascun che potrebbe rendere più semplice:

public static class EnumerableExtensions
{
    public static void Each<T>(this IEnumerable<T> col, Action<T> itemWorker)
    {
        foreach (var item in col)
        {
            itemWorker(item);
        }
    }
}

E chiamarlo in questo modo:

// Declare variables in parent scope
double weight;
double length;
int items;

ArticleLedgerEntries
    .Where(
        pd => 
           pd.LedgerEntryType == LedgerEntryTypeTypes.Unload &&
           pd.InventoryType == InventoryTypes.Finished
    )
    .Each(
        pd => 
        {
            // Close around variables defined in parent scope
            weight += pd.GrossWeight; 
            lenght += pd.Length;
            items += pd.NrDistaff;
        }
    );

UPDATE: Solo una nota aggiuntiva. L'esempio di cui sopra si basa su una chiusura. Il peso variabili, la lunghezza e articoli dovrebbe essere dichiarato in un ambito genitore, permettendo loro di persistono oltre ogni chiamata all'azione itemWorker. Ho aggiornato l'esempio per riflettere questo per amor di chiarezza.

Altri suggerimenti

È possibile chiamare Sum tre volte, ma sarà più lento perché renderà tre anelli.

Ad esempio:

var list = ArticleLedgerEntries.Where(pd => pd.LedgerEntryType == LedgerEntryTypeTypes.Unload
                                   && pd.InventoryType == InventoryTypes.Finished))

var totalWeight = list.Sum(pd => pd.GrossWeight);
var totalLength = list.Sum(pd => pd.Length);
var items = list.Sum(pd => pd.NrDistaff); 

A causa di esecuzione ritardata, sarà anche rivalutare la chiamata Where ogni volta, anche se questo non è una questione nel tuo caso. Ciò può essere evitato chiamando ToArray, ma che provoca un'allocazione matrice. (E sarebbe ancora correre tre anelli)

Tuttavia, se non si dispone di un gran numero di voci o di esecuzione di questo codice in un loop stretto, non è necessario preoccuparsi di prestazioni.


Modifica : se davvero desidera utilizzare LINQ, si potrebbe abusare Aggregate, in questo modo:

int totalWeight, totalLength, items;

list.Aggregate((a, b) => { 
    weight += detail.GrossWeight;
    length += detail.Length;
    items  += detail.NrDistaff;
    return a;
});

Questa è fenomenale codice brutto, ma deve eseguire quasi come un loop dritto.

Si potrebbe anche riassumere nell'accumulatore, (vedi esempio qui sotto), ma questo potrebbe allocare un oggetto temporaneo per ogni elemento nella vostra lista, che è un'idea stupida. (Tipi anonimi sono immutabili)

var totals = list.Aggregate(
    new { Weight = 0, Length = 0, Items = 0},
    (t, pd) => new { 
        Weight = t.Weight + pd.GrossWeight,
        Length = t.Length + pd.Length,
        Items = t.Items + pd.NrDistaff
    }
);

Si potrebbe anche gruppo dal vero - 1 (che in realtà è compresa qualsiasi degli elementi e poi li hanno contati o estivazione):

 var results = from x in ArticleLedgerEntries
                       group x by 1
                       into aggregatedTable
                       select new
                                  {
                                      SumOfWeight = aggregatedTable.Sum(y => y.weight),
                                      SumOfLength = aggregatedTable.Sum(y => y.Length),
                                      SumOfNrDistaff = aggregatedTable.Sum(y => y.NrDistaff)
                                  };

Per quanto riguarda il tempo di esercizio, è quasi buono come il ciclo (con una costante aggiunta).

Si sarebbe in grado di fare questo perno in stile, utilizzando la risposta in questa discussione: E 'possibile ruotare i dati utilizzando LINQ?

Ok. Mi rendo conto che non c'è un modo semplice per farlo utilizzando LINQ. Prenderò può foreach ciclo perché ho capito che non è così male. Grazie a tutti voi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top