Ad esempio:C'è una dichiarazione di anteporre un elemento T ad un IEnumerable <T>
string element = 'a';
IEnumerable<string> list = new List<string>{ 'b', 'c', 'd' };
IEnumerable<string> singleList = ???; //singleList yields 'a', 'b', 'c', 'd'
Ad esempio:C'è una dichiarazione di anteporre un elemento T ad un IEnumerable <T>
string element = 'a';
IEnumerable<string> list = new List<string>{ 'b', 'c', 'd' };
IEnumerable<string> singleList = ???; //singleList yields 'a', 'b', 'c', 'd'
prendo esso è possibile non solo Insert
nella lista esistente?
Bene, è possibile utilizzare new[] {element}.Concat(list)
.
In caso contrario, si potrebbe scrivere il proprio metodo di estensione:
public static IEnumerable<T> Prepend<T>(
this IEnumerable<T> values, T value) {
yield return value;
foreach (T item in values) {
yield return item;
}
}
...
var singleList = list.Prepend("a");
No, non esiste una built-in statment, dichiarazione, ma è banale da implementare tale funzione:
IEnumerable<T> PrependTo<T>(IEnumerable<T> underlyingEnumerable, params T[] values)
{
foreach(T value in values)
yield return value;
foreach(T value in underlyingEnumerable)
yield return value;
}
IEnumerable<string> singleList = PrependTo(list, element);
Puoi persino renderlo un metodo di estensione se la versione C# lo consente.
Si può rotolare il proprio:
static IEnumerable<T> Prepend<T>(this IEnumerable<T> seq, T val) {
yield return val;
foreach (T t in seq) {
yield return t;
}
}
E poi usarlo:
IEnumerable<string> singleList = list.Prepend(element);
Penso che dovrebbe essere "yield return t" all'interno del foreach e il metodo dovrebbe essere statico –
public static class IEnumerableExtensions
{
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> ie, T item)
{
return new T[] { item }.Concat(ie);
}
}
Look mi piace che tu concordi l'oggetto fino alla fine, non anteponendolo ... –
Oops, buon punto. Modificherò ... – BFree
Questo lo farebbe ...
IEnumerable<string> singleList = new[] {element}.Concat(list);
Se si voleva la lista singola per essere una lista quindi ...
IEnumerable<string> singleList = new List<string>() {element}.Concat(list);
... funziona anche.
anche:
IEnumerable<string> items = Enumerable.Repeat(item, 1).Concat(list);
Trovo conveniente per essere in grado di anteporre più elementi in modo chainable. Questa versione sfrutta i metodi di estensione e params
.
Come nota, questa versione consente implicitamente null
, ma è altrettanto semplice cambiarlo in throw new NullReferenceException()
se questo è il comportamento desiderato.
public static class IEnumerableExtensions
{
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, params T[] items)
{
return items.Concat(source ?? new T[0]);
}
}
consente una sintassi molto leggibile per i singoli elementi:
GetItems().Prepend(first, second, third);
... e per le collezioni di elementi:
GetItems().Prepend(GetMoreItems());
di finitura l'esempio dei risultati della domanda in:
string element = "a";
IEnumerable<string> list = new List<string>{ "b", "c", "d" };
IEnumerable<string> singleList = list.Prepend(element);
Sembra che tu abbia un errore di battitura in cui fai riferimento a 'source' ma dichiari' sources'? – NetMage
@ NetMage, grazie per averlo capito. – zzzzBov
Nessun problema, questo è il mio preferito da 'Prepend' - sfortunatamente non è quello .Net Core e .Net Standard 2.0 aggiunto. – NetMage
Proprio come un promemoria - Elenco < T> non è l'unico tipo di contenitore. Se ti ritrovi ad aggiungere elementi in primo piano nella lista abbastanza spesso, puoi anche considerare l'utilizzo di Stack < T> per implementare il tuo contenitore.Una volta che hai uno stack
var container = new Stack<string>(new string[] { "b", "c", "d" });
si può sempre "anteporre" un elemento tramite
container.Push("a");
e ancora usare la collezione come IEnumerable < T> come in
foreach (var s in container)
// do sth with s
oltre tutti gli altri metodi tipici di una pila come Pop(), Peek(), ...
Alcune delle soluzioni sopra iterate attraverso l'intero IEnumeration < T> solo per anteporre un elemento (o più di uno in un caso). Questa può essere un'operazione molto costosa se la tua collezione contiene un gran numero di elementi e la frequenza di prepending è relativamente alta.
Guardando alcuni esempi, penso che preferirei invertire l'estensione per applicare all'oggetto.
public static IEnumerable<T> PrependTo<T>(this T value, IEnumerable<T> values) {
return new[] { value }.Concat(values);
}
Usato come
var singleList = element.PrependTo(list);
In .NET core è built-in: '' '' public static System.Collections.Generic.IEnumerable Prepend (questo System.Collections.Generic.IEnumerable Fonte , elemento TSource); '' '' (https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.prepend?view=netcore-2.0) –
E come parte dell'implementazione .Net Standard 2.0, è incluso in .Net 4.7.1. – NetMage