2010-03-24 5 views
7

Quiero añadir dos listas de un tipo numérico tal que addedList [x] = LISTONE [x] + listTwo [x]¿Cómo agrego dos listas en Linq así que addedList [x] = listOne [x] + listTwo [x]?

La salida de la lista tiene que ser un Generic.IEnumerable que puedo usar en futuras consultas de linq.

Si bien pude hacerlo usando el siguiente código, no puedo evitar sentir que debe haber una manera mejor. ¿Algunas ideas?

List<int> firstList = new List<int>(new int[] { 1, 3, 4, 2, 5, 7, 2, 5, 7, 8, 9, 0 }); 
List<int> secondList = new List<int>(new int[] { 4, 6, 8, 3, 1, 5, 9, 3, 0 }); 

int findex = 0; 

ILookup<int, int> flookup = firstList.ToLookup(f => 
          { 
           int i = findex; 
           findex++; 
           return i; 
           }, p => p); 

var listsAdded = from grp in flookup 
       select grp.First() + secondList.ElementAtOrDefault(grp.Key); 

foreach (int i in listsAdded) 
    Console.WriteLine(i); 
+0

¿Qué sucede cuando la segunda lista es más larga que la primera? – Gabe

+0

@gabe - vea mi solución a continuación, maneja listas de diferentes longitudes. –

Respuesta

3
var result = 
    from i in 
     Enumerable.Range(0, Math.Max(firstList.Count, secondList.Count)) 
    select firstList.ElementAtOrDefault(i) + secondList.ElementAtOrDefault(i); 
+0

Esto es exactamente lo que estaba buscando. Gracias Artem. – Audie

+0

Advertencia: este enfoque puede ser terriblemente ineficiente, especialmente para listas de cualquier tamaño significativo. Cada llamada a 'ElementAtOrDefault' puede necesitar iterar a través de la lista desde el principio. Combinar dos listas de 100 elementos puede generar el costo de iterar 10,100 elementos en lugar de solo 200. Para 1000 elementos, se convierte en 1,001,000 elementos. Y a partir de ahí empeora rápidamente ... – Enigmativity

+2

@Enigmatividad, esto no es cierto en un contexto dado. Teniendo en cuenta que se llama a ElementAtOrDefault (IList en general), el tamaño de la lista realmente no importa porque lo que ElementAtOrDefault (índice) hace internamente es la lista de llamadas [índice] que accede a la matriz interna por índice, por lo que el acceso es O (1) y no iterar nada de lo que dices. ElementAtOrDefault puede comportarse como usted indicó para aquellos IEnumerable que no son del tipo IList (pero este no es el caso de esta pregunta). –

0
var res = list.Concat(list1); 

concatena dos listas, incluyendo duplicados eventuales.

var res = list.Union(list1); 

concatena dos listas, proporcionando un resultado sin duplicados.

3

Parece que usted quiere una función como esta:

public static IEnumerable<int> SumIntLists( 
    this IEnumerable<int> first, 
    IEnumerable<int> second) 
{ 
    using(var enumeratorA = first.GetEnumerator()) 
    using(var enumeratorB = second.GetEnumerator()) 
    { 
     while (enumeratorA.MoveNext()) 
     { 
      if (enumeratorB.MoveNext()) 
       yield return enumeratorA.Current + enumeratorB.Current; 
      else 
       yield return enumeratorA.Current; 
     } 
     // should it continue iterating the second list? 
     while (enumeratorB.MoveNext()) 
      yield return enumeratorB.Current; 
    } 
} 
+0

Gracias Gabe. Este es un excelente ejemplo de una extensión que resolvería mi problema. Esperaba poder hacer esto sin escribir una extensión, como lo hizo Artem. Sin embargo, su ejemplo de extensión fue instructivo, y me gustó la forma en que manejó las diferentes longitudes de lista. Gracias por tu ayuda. – Audie

15

Lo que estás buscando es un método Zip. Este método le permite combinar listas de igual longitud en una sola lista aplicando una proyección.

Por ejemplo

var sumList = firstList.Zip(secondList, (x,y) => x + y).ToList(); 

se añadió este método a la BCL en CLR 4,0 (Reference). Sin embargo, es bastante sencillo implementarlo y hay muchas versiones disponibles en línea que se pueden copiar en una aplicación 2.0 o 3.5.

+0

¿Cómo maneja Zip las secuencias de diferentes tamaños? – Gabe

+0

@gabe, diferentes implementaciones toman diferentes rutas. La versión BCL ignorará los elementos adicionales en la lista más larga, pero es bastante fácil escribir un método diferente que amplíe la lista. – JaredPar

Cuestiones relacionadas