2012-08-01 10 views
5

Supponiamo che ho questa lista di numeri:articoli Gruppo di importo totale

List<int> nu = new List<int>(); 
nu.Add(2); 
nu.Add(1); 
nu.Add(3); 
nu.Add(5); 
nu.Add(2); 
nu.Add(1); 
nu.Add(1); 
nu.Add(3); 

Mantenere le voci di elenco nello stesso ordine, è possibile raggruppare gli elementi in LINQ che sono somma di 6 quindi i risultati sarebbe qualcosa in questo modo:

2,1,3 - 5 - 2,1,1 - 3 
+2

tuo il risultato non è un raggruppamento di "meno di 7". Tutti i numeri sono inferiori a 7. – abatishchev

+3

La somma di ogni gruppo è inferiore a 7 – Johnny5

+0

Perché sarebbe (2,1,3) essere in un gruppo di spearate in (5)? Sono entrambi meno di 7 – saj

risposta

4

Si potrebbe fare con Aggregate.

(Nota a margine: Utilizzare LINQPad per testare/scrivere questi tipi di query, lo rende facile)

dà a questi risultati:

results

Ti piace questa:

class Less7Holder 
{ 
    public List<int> g = new List<int>(); 
    public int mySum = 0; 
} 

void Main() 
{ 
    List<int> nu = new List<int>(); 
    nu.Add(2); 
    nu.Add(1); 
    nu.Add(3); 
    nu.Add(5); 
    nu.Add(2); 
    nu.Add(1); 
    nu.Add(1); 
    nu.Add(3); 

    var result = nu .Aggregate(
     new LinkedList<Less7Holder>(), 
     (holder,inItem) => 
     { 
      if ((holder.Last == null) || (holder.Last.Value.mySum + inItem >= 7)) 
      { 
      Less7Holder t = new Less7Holder(); 
      t.g.Add(inItem); 
      t.mySum = inItem; 
      holder.AddLast(t); 
      } 
      else 
      { 
      holder.Last.Value.g.Add(inItem); 
      holder.Last.Value.mySum += inItem; 
      } 
      return holder; 
     }, 
     (holder) => { return holder.Select((h) => h.g);}); 

    result.Dump(); 

} 
+0

+1 per la soluzione in LINQ come richiesto –

6

Risolvere questo con LINQ direttamente sarebbe fastidio, invece si potrebbe fare un metodo di estensione:

// Assumptions: 
// (1) All non-negative, or at least you don't mind them in your sum 
// (2) Items greater than the sum are returned by their lonesome 
static IEnumerable<IEnumerable<int>> GroupBySum(this IEnumerable<int> source, 
    int sum) 
{ 
    var running = 0; 
    var items = new List<int>(); 
    foreach (var x in source) 
    { 
     if (running + x > sum && items.Any()) 
     { 
      yield return items; 
      items = new List<int>(); 
      running = 0; 
     } 

     running += x; 
     items.Add(x); 
    } 

    if (items.Any()) yield return items; 
} 
+1

Stavo scrivendo codice simile da solo - ma perché chiamare 'ToArray' ogni volta e cancellare l'elenco esistente? Perché non restituire l'elenco e crearne uno nuovo ogni volta? –

+0

Concerto di estrazione rapida di Good 'ol SE. Il 73% è stato terminato con lo stesso metodo di estensione quando è stato pubblicato. –

+0

@JonSkeet: nessuna ragione; grazie per la recensione (aggiornata). – user7116

Problemi correlati