2009-06-01 13 views
11

¿Hay alguna manera de convertir una colección de objetos en un único objeto nuevo usando LINQ?¿Hay un LINQ equivalente a string.Join (string, string [])

Quiero usar esto dentro de otra expresión LINQ to SQL.

+6

Usted * * efectivamente hizo esta día de hoy (http://stackoverflow.com/questions/934327) - LINQ no ha cambiado desde entonces –

+0

@Marc Gravell Gracias. Soy consciente de que LINQ no ha cambiado en la última hora o así, solo estaba tratando de obtener una aclaración sobre cómo hacer la concatenación. –

+0

La respuesta de @Marc Gravell en (http://stackoverflow.com/questions/934327) y la respuesta de @Jon Skeet a continuación son correctas. Las respuestas de @bruno conde y @Scott Ivey son incorrectas. Por lo tanto, debe marcar la respuesta de @Jon Skeet como la respuesta aceptada. –

Respuesta

19

¿Por qué no se utiliza el string.Join en sí?

string.Join("<br/>", collection.Select(e => e.TextProp).ToArray()); 
+3

El problema es que dudo que se traduzca a SQL. Tal vez lo haga, pero lo dudo. Si funciona, me alegra que elimine por completo mi respuesta :) –

+2

Después de una prueba rápida con linqpad, no creo que esto se traduzca a SQL. Si el OP necesita que esto se traduzca, creo que debería optar por un procedimiento almacenado como usted o Marc han sugerido. –

+0

Maldita sea, ¿por qué no veo esto? Construí mi propio método de extensión para hacer esto y todo. –

7

La manera normal sería utilizar uno de los operadores de agregación (Aggregate, Sum, Average etc), pero es del todo depende del tipo y lo que quiere hacer. ¿En qué tipo estás interesado?

EDITAR: Bien, así que quieres concatenar cadenas ... Yo no creo que hay algo que haga eso en LINQ to SQL. Opciones:

  • Escribir un procedimiento almacenado o TVF lo hagan en SQL
  • Fetch las cuerdas individuales en LINQ to SQL y concatenar nuevo en el lado del cliente
+0

Es cadena, y quiero anexar usando una cadena de separación, p. ej. "," o "
". –

+0

@ OP. ¿Por qué no usar StringBuilder si solo está agregando cadenas? – Gishu

+0

@Jon OT ¿Pero podría echar un vistazo a la pregunta 926352 ... puede atar los cabos sueltos en mi comprensión? – Gishu

12

Usted puede utilizar el método agregado ...

var myResults = (from myString in MyStrings 
       select myString) 
       .Aggregate(string.Empty, (results, nextString) 
        => string.Format("{0}<br />{1}", results, nextString)); 

o

var myResults = MyStrings.Aggregate(string.Empty, (results, nextString) 
        => string.Format("{0}<br />{1}", results, nextString)); 
+3

Esto funciona bien para enumerable de cadenas, pero no parece ser compatible con LINQ to SQL (OP escribió que quería usar esto dentro de otra expresión LINQ to SQL): lanza NotSupportedException con el mensaje "El operador de consulta 'Agregado' no es soportado." –

3

La mayoría de las soluciones aquí son bastante ineficaz si tiene un gran número de valores desea concatonate . Además, no son tan legibles. Si va a hacer este tipo de cosas con frecuencia, entonces vale la pena construir su propio método de extensión para hacerlo. La implementación a continuación le permite hacer el equivalente a string.Join(", ", arrayOfStrings) donde arrayOfStrings puede ser IEnumerable<T>, y el separador puede ser cualquier objeto. Se le permite hacer algo como esto:

var names = new [] { "Fred", "Barney", "Wilma", "Betty" }; 
var list = names 
    .Where(n => n.Contains("e")) 
    .Join(", "); 

Dos cosas que me gusta de esto son:

  1. Es muy fácil de leer en un contexto de LINQ.
  2. Es bastante eficiente porque usa StringBuilder y evita evaluar la enumeración dos veces, lo que es importante en un escenario de base de datos (L2S, L2E o L2Nh).
public static string Join<TItem,TSep>( 
    this IEnumerable<TItem> enuml, 
    TSep     separator) 
{ 
    if (null == enuml) return string.Empty; 

    var sb = new StringBuilder(); 

    using (var enumr = enuml.GetEnumerator()) 
    { 
     if (null != enumr && enumr.MoveNext()) 
     { 
      sb.Append(enumr.Current); 
      while (enumr.MoveNext()) 
      { 
       sb.Append(separator).Append(enumr.Current); 
      } 
     } 
    } 

    return sb.ToString(); 
} 
Cuestiones relacionadas