Quindi abbiamo diversi sotto-problemi qui. Il primo problema è restituire l'elemento in una raccolta con il valore più alto di una proiezione di quell'articolo. Max
confronta solo l'elemento stesso o, se fornita una proiezione, restituisce il risultato di tale proiezione.
public static TSource MaxBy<TSource, TKey>(this IEnumerable<TSource> source
, Func<TSource, TKey> selector
, IComparer<TKey> comparer = null)
{
if (comparer == null)
{
comparer = Comparer<TKey>.Default;
}
using (IEnumerator<TSource> iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
throw new ArgumentException("Source was empty");
}
TSource maxItem = iterator.Current;
TKey maxValue = selector(maxItem);
while (iterator.MoveNext())
{
TKey nextValue = selector(iterator.Current);
if (comparer.Compare(nextValue, maxValue) > 0)
{
maxValue = nextValue;
maxItem = iterator.Current;
}
}
return maxItem;
}
}
Questo ci permette di molto più efficiente ottenere l'indice dell'elemento con il valore più grande:
var splitPoint = list.Select((index, number) => new { index, number })
.MaxBy(pair => pair.number)
.index;
Accanto a dividere la collezione si può semplicemente utilizzare Skip/prendere:
var firstHalf = list.Take(index);
var secondHalf = list.Skip(index + 1);
Ci sono una serie di diversi problemi con il codice che hai risolto qui.
di calcolare il valore Max
per ogni singolo articolo nella query per ottenere item
, invece di calcolare una volta e utilizzando quel valore calcolato.
Quindi, per ogni articolo nell'elenco, e copiare tutti gli elementi in un nuovo elenco, due volte, cercare in quell'elenco per cercare di trovare la posizione dell'elemento massimo, quindi provare a trovare la posizione dell'elemento corrente. Quindi fai tutto questo due volte. Ciò significa che copi l'intero array in un elenco quattro volte per ogni elemento, cerca la posizione dell'elemento massimo quattro volte per elemento nell'insieme e cerca linearmente l'elenco per trovare l'indice dell'elemento corrente (qualcosa puoi calcolare in un tempo non breve contando semplicemente) due volte per ogni oggetto. Questo si ridurrà ... male, man mano che aumenta il numero di elementi.
Il codice qui trova l'indice della voce massima in un singolo passaggio della raccolta e quindi crea sequenze che rappresentano ciascuna metà che non hanno praticamente nessun sovraccarico oltre al semplice iterare attraverso tali elementi.
Prima di tutto si potrebbe semplicemente usare 'int item = list.Max()'. – Vache
In secondo luogo, sembra che si desideri utilizzare ['Except'] (http://msdn.microsoft.com/en-us/library/vstudio/bb300779%28v=vs.100%29.aspx)? – Default
@Default ho letto su Tranne - sembra che rimuova un elemento da un elenco - non riesco a vedere come dividerei il risultato in due elementi IEnumerable nello splitpoint. – Johannes