Konvertieren Sie eine Liste von Objekten mit einem Lambda-Ausdruck von einem Typ in einen anderen


224

Ich habe eine foreach-Schleife, die eine Liste von Objekten eines Typs liest und eine Liste von Objekten eines anderen Typs erstellt. Mir wurde gesagt, dass ein Lambda-Ausdruck das gleiche Ergebnis erzielen kann.

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

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

Jede Hilfe wäre dankbar - ich bin neu bei Lambda und Linq, danke, s


@mmcrae diese Frage ist neuer als diese
Andy Wiesendanger

Antworten:


312

Versuche Folgendes

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

Hierbei wird eine Kombination aus Lambdas und LINQ verwendet, um die Lösung zu erzielen. Die Select-Funktion ist eine Projektionsmethode, bei der der übergebene Delegat (oder in diesem Fall Lambda) auf jeden Wert in der ursprünglichen Sammlung angewendet wird. Das Ergebnis wird in einem neuen zurückgegeben IEnumerable<TargetType>. Der Aufruf von .ToList ist eine Erweiterungsmethode, die dies IEnumerable<TargetType>in eine konvertiert List<TargetType>.


Gibt es eine Möglichkeit, dies ohne eine konkrete Implementierung zu tun TargetType? Am Ende hatte ich so etwas: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList();Wo das Ziel war, ein Objekt vom Typ zu bekommenList<ISearchEntity>
Aaron Newton

220

Wenn Sie wissen , Sie konvertieren möchten , List<T1>um List<T2>dann List<T>.ConvertAllwird etwas effizienter als Select/ ToListweil es die genaue Größe kennt , mit zu beginnen:

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

Im allgemeineren Fall, wenn Sie nur die Quelle als kennen IEnumerable<T>, ist die Verwendung von Select/ ToListder richtige Weg. Man könnte auch argumentieren, dass es in einer Welt mit LINQ zunächst idiomatischer ist ... aber es lohnt sich zumindest, sich der ConvertAllOption bewusst zu sein .


1
Zuerst dachte ich nicht, dass ich das tun könnte, weil ich es mit einer ienumerable zu tun hatte (für die Quellliste und es gibt keine Konvertierungsoption), also habe ich .ToList () darauf aufgerufen und jetzt versuche ich die Konvertierung - i mag es besser, als ein nicht filterendes "wo"
einzufügen

2
Warum brauchst du ein wo? Wenn Sie nur IEnumerable<T>dann haben, rufen Sie einfach an Selectund ToListlaut Jareds Antwort.
Jon Skeet

Für andere Neulinge wie mich können Sie auch eine Methode wiex => buildTargetType(x)
Snekse

55
var target = origList.ConvertAll(x => (TargetType)x);

1
Was ist diese Syntax? Dies erinnert nicht an ein Lambda. Einige Dokumentationslink wäre dankbar. Vielen Dank, es funktioniert gut hier
Pierre de LESPINAY

Das Argument für ConvertAll ist ein reguläres C # -Lambda, oder?
avl_sweden

1
sieht gut aus, braucht aber einen Kontext, wann (oder ob) es verwendet werden kann. Ich habe es gerade versucht und bekam eine cannot cast expressionAusnahme
Collin M. Barrett

31
List<target> targetList = new List<target>(originalList.Cast<target>());

5
-1 Dies würde nur funktionieren, wenn Casting möglich wäre und im Fall von OPs scheint es so zu sein.
Mike Zboray

Funktioniert wie erwartet! benötigt, um List <Objekt> in List <RealType> zu konvertieren
Elo

20

Ich glaube, so etwas sollte funktionieren:

origList.Select(a => new TargetType() { SomeValue = a.SomeValue});

1
Sie müssen .ToList()am Ende ein hinzufügen , andernfalls wird einfach eine IEnumerable bereitgestellt.
MattD

10

Hier ist ein einfaches Beispiel.

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

List<string> s = c.Select(x => x.ToString()).ToList();

1
Super ... genau das, wonach ich gesucht habe! Nun, nicht ganz genau ... Ich wollte nur eine Eigenschaft für jedes Element in der Liste, aber Sie haben mir die Lamba-Syntax gegeben, ohne zu weit scrollen zu müssen. ;)
fehlerhafter

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

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

3

Angenommen, Sie haben mehrere Eigenschaften, die Sie konvertieren möchten.

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 })

2

Oder mit einem constructor& linqmit 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();  

Die LinqLinie ist weicher! ;-);


0

Wenn Sie eine Funktion zum Wirken verwenden müssen:

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

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

Wo meine benutzerdefinierte Funktion ist:

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

0

für ähnliche Typklasse.

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


Vielen Dank. Es ist höllisch teuer für Server und entspricht nicht den Best Practices, funktioniert aber hervorragend. Ich habe es zum Konvertieren der ersten Klassen der EF-Datenbank verwendet, wenn mehrere Prozeduren dieselben 5 Spalten zurückgeben, nur für unterschiedliche "where-Klauseln" in den Prozeduren. Ich weiß, ich hätte einen Tabellentyp in der Datenbank
erstellen sollen

-1

Wenn die Typen direkt gegossen werden können, ist dies der sauberste Weg, dies zu tun:

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

Wenn die Typen nicht direkt umgewandelt werden können, können Sie die Eigenschaften vom ursprünglichen Typ dem Zieltyp zuordnen.

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

-1

Wir werden den ersten Listentyp als String betrachten und ihn in den Integer-Listentyp konvertieren wollen.

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

Fügen Sie Werte in die ursprüngliche Liste ein.

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

Zielliste vom Integer-Typ erstellen

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

Listenwerte mit forEach drucken:

    targetLambdaList.forEach(System.out::println);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.