convertir una lista de objetos de un tipo a otro usando la expresión lambda

224

Tengo un bucle foreach que lee una lista de objetos de un tipo y produce una lista de objetos de un tipo diferente. Me dijeron que una expresión lambda puede lograr el mismo resultado.

var origList = List<OrigType>(); // assume populated
var targetList = List<TargetType>(); 

foreach(OrigType a in origList) {
    targetList.Add(new TargetType() {SomeValue = a.SomeValue});
}

Cualquier ayuda sería apreciada, soy nuevo en lambda y linq gracias, s

Stratton
fuente
@mmcrae esa pregunta es más nueva que esta
Andy Wiesendanger el

Respuestas:

312

Intenta lo siguiente

var targetList = origList
  .Select(x => new TargetType() { SomeValue = x.SomeValue })
  .ToList();

Esto está utilizando una combinación de Lambdas y LINQ para lograr la solución. La función Seleccionar es un método de estilo de proyección que aplicará el delegado pasado (o lambda en este caso) a todos los valores de la colección original. El resultado será devuelto en un nuevo IEnumerable<TargetType>. La llamada .ToList es un método de extensión que lo convertirá IEnumerable<TargetType>en un List<TargetType>.

JaredPar
fuente
¿Hay alguna manera de hacer esto sin tener una implementación concreta TargetType? Terminé con algo como esto: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList();donde el objetivo era obtener un objeto de tipoList<ISearchEntity>
Aaron Newton
220

Si sabe que desea convertir de List<T1>a, List<T2>entonces List<T>.ConvertAllserá un poco más eficiente que Select/ ToListporque sabe el tamaño exacto para comenzar:

target = orig.ConvertAll(x => new TargetType { SomeValue = x.SomeValue });

En el caso más general, cuando solo conoces la fuente como un IEnumerable<T>, usar Select/ ToListes el camino a seguir. También podría argumentar que en un mundo con LINQ, es más idiomático comenzar ... pero al menos vale la pena conocer la ConvertAllopción.

Jon Skeet
fuente
1
al principio no pensé que podría hacer esto, porque estaba lidiando con un número innumerable (para la lista de origen y no proporciona una opción de conversión), así que llamé a .ToList () y ahora estoy tratando de convertir todo - i me gusta más que poner un 'dónde' sin filtro
Stratton
2
¿Por qué necesitarías un dónde? Si solo tienes IEnumerable<T>, simplemente llama Selecty ToListsegún la respuesta de Jared.
Jon Skeet
Para otros novatos como yo, también puedes llamar a un método comox => buildTargetType(x)
Snekse
55
var target = origList.ConvertAll(x => (TargetType)x);
Montaña
fuente
1
¿Qué es esta sintaxis? Esto no se parece a una lambda. Se agradecería algún enlace de documentación. Gracias, sin embargo, funciona bien aquí
Pierre de LESPINAY
El argumento para ConvertAll es una lambda C # normal, ¿verdad?
avl_sweden
1
se ve bien, pero necesita algo de contexto cuando (o si) se puede usar. Lo intenté y recibí una cannot cast expressionexcepción
Collin M. Barrett, el
31
List<target> targetList = new List<target>(originalList.Cast<target>());
Pranav
fuente
55
-1 esto solo funcionaría si fuera posible la conversión y en el caso de los OP parece ser así.
Mike Zboray
Funciona como se esperaba! necesario para convertir List <object> en List <RealType>
Elo
20

Creo que algo como esto debería funcionar:

origList.Select(a => new TargetType() { SomeValue = a.SomeValue});
Andy White
fuente
1
.ToList()Debe agregar un al final, de lo contrario, esto simplemente proporcionará un IEnumerable.
MattD
10

Aquí hay un ejemplo simple ...

List<char> c = new List<char>() { 'A', 'B', 'C' };

List<string> s = c.Select(x => x.ToString()).ToList();
Ian P
fuente
1
Impresionante ... ¡exactamente lo que estaba buscando! Bueno, no exactamente ... Solo quería una propiedad de cada Elemento en la lista, pero me diste la sintaxis de lamba sin tener que desplazarte demasiado. ;)
error
7
var list1 = new List<Type1>();
var list2 = new List<Type2>();

list1.ForEach(item => list2.Add(new Type2() { Prop1 = value1 }));
Chris Arnold
fuente
3

Suponga que tiene varias propiedades que desea convertir.

public class OrigType{
    public string Prop1A {get;set;}
    public string Prop1B {get;set;}
}

public class TargetType{
    public string Prop2A {get;set;}
    public string Prop2B {get;set;}
}

var list1 = new List<OrigType>();
var list2 = new List<TargetType>();

list1.ConvertAll(x => new OrigType { Prop2A = x.Prop1A, Prop2B = x.Prop1B })
Max Chu
fuente
2

O con un constructor& linqcon Select:

public class TargetType {
  public string Prop1 {get;set;}
  public string Prop1 {get;set;}

  // Constructor
  public TargetType(OrigType origType) {
    Prop1 = origType.Prop1;
    Prop2 = origType.Prop2;
  }
}

var origList = new List<OrigType>();
var targetList = origList.Select(s=> new TargetType(s)).ToList();  

¡La Linqlínea es más suave! ;-)

A. Morel
fuente
0

Si necesita usar una función para emitir:

var list1 = new List<Type1>();
var list2 = new List<Type2>();

list2 = list1.ConvertAll(x => myConvertFuntion(x));

Donde mi función personalizada es:

private Type2 myConvertFunction(Type1 obj){
   //do something to cast Type1 into Type2
   return new Type2();
}
jaimenino
fuente
0

para una clase de tipo similar.

List<targetlist> targetlst= JsonConvert.DeserializeObject<List<targetlist>>(JsonConvert.SerializeObject(<List<baselist>));

Arun Solanki
fuente
Muchas gracias. Es caro como el infierno para el servidor y no está de acuerdo con las mejores prácticas, pero funciona espléndidamente. Lo usé para convertir las primeras clases de la base de datos EF cuando múltiples procedimientos devuelven las mismas 5 columnas como resultado, solo para diferentes "cláusulas where" en los procedimientos. Sé que debería haber hecho el tipo de tabla en la base de datos, pero no fui el diseñador de eso ...
jo1storm
-1

Si los tipos se pueden lanzar directamente, esta es la forma más limpia de hacerlo:

var target = yourList.ConvertAll(x => (TargetType)x);

Si los tipos no se pueden emitir directamente, puede asignar las propiedades del tipo original al tipo de destino.

var target = yourList.ConvertAll(x => new TargetType { SomeValue = x.SomeValue });
Ayo Adesina
fuente
-1

Consideraremos que el primer tipo de Lista es Cadena y queremos convertirlo en un tipo de Lista Entero.

List<String> origList = new ArrayList<>(); // assume populated

Agregar valores en la lista original.

origList.add("1");
origList.add("2");
    origList.add("3");
    origList.add("4");
    origList.add("8");

Crear lista de destino de tipo entero

List<Integer> targetLambdaList = new ArrayList<Integer>();
targetLambdaList=origList.stream().map(Integer::valueOf).collect(Collectors.toList());

Imprimir los valores de la lista con forEach:

    targetLambdaList.forEach(System.out::println);
Garima Garg
fuente