2010-08-04 5 views
9

Necesito anteponer un valor único a un IEnumerable (en este caso, IEnumerable<string[]>). Con el fin de hacer eso, estoy creando una List<T> sólo para envolver el primer valor para que pueda llamar Concat:¿Cuál es una manera fácil de agregar o anteponer un único valor a un IEnumerable <T>?

// get headers and data together 
IEnumerable<string[]> headers = new List<string[]> { 
    GetHeaders() 
}; 
var all = headers.Concat(GetData()); 

Yuck. ¿Hay una mejor manera? ¿Y cómo manejarías el caso opuesto de agregar un valor?

Respuesta

23

escribí métodos de extensión personalizados para hacer esto:

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T item) 
{ 
    foreach (T i in source) 
     yield return i; 

    yield return item; 
} 

public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T item) 
{ 
    yield return item; 

    foreach (T i in source) 
     yield return i; 
} 

En su escenario, podría escribir:

var all = GetData().Prepend(GetHeaders()); 

Como comentó chilltemp, esto no muta la colección original. En la verdadera moda de Linq, genera un nuevo IEnumerable<T>.

Nota: Se recomienda una comprobación argumento nulo ávido de source, pero no se muestra por razones de brevedad.

+0

¡Agradable! Tengo algunos en mi biblioteca como esos. – kbrimington

+3

Elegante. Se debe tener en cuenta que esto devolverá un nuevo IEnumerable al enumerar la colección existente. En realidad, no agrega/precede la colección original. – chilltemp

7

Utilice el método de extensión Enumerable.Concat. Para agregar valores en lugar de anteponer, simplemente debe llamar al Concat en reversa. (Es decir: GetData().Concat(GetHeaders());)

Si GetHeaders() devuelve una única matriz de cadenas, yo personalmente, probablemente, lo envuelve en un único conjunto de elementos en lugar de una lista:

var all = (new[] {GetHeaders()}).Concat(GetData()); 
+0

getHeaders() devuelve 'string [] ', GetData() devuelve' ' IEnumerable. ¿Has leído mi pregunta? –

+0

@Gabe: Esto funcionará con la cadena [] e IEnumerable - las matrices implementan IEnumerable . Si su cadena [] es ** cadena **, sin embargo, las cosas son un poco diferentes. Su pregunta no fue increíblemente clara aquí. –

+0

@Reed correcto, comenté antes de decir tu edición –

1

Rx contiene el método StartWith que antepone el valor a la secuencia. También Return puede ajustar el valor como secuencia para que pueda adjuntarse a través de Concat.

 var c = new[] {4}; 
     var c1 = c.StartWith(1, 2, 3); 
     var c2 = c1.Concat(EnumerableEx.Return(5)); 

     c2.Run(Console.Write); // 12345 
0

Otra opción es un método de ayuda que crea una secuencia de un solo elemento:

public static class EnumerableExt 
{ 
    public static IEnumerable<T> One<T>(T item) 
    { 
     yield return item; 
    } 
} 

... 
//prepend: 
EnumerableExt.One(GetHeaders()).Concat(GetData()); 

//append: 
GetData().Concat(EnumerableExt.One(GetHeaders()); 
Cuestiones relacionadas