converte un elenco di oggetti da un tipo a un altro usando l'espressione lambda


224

Ho un ciclo foreach che legge un elenco di oggetti di un tipo e produce un elenco di oggetti di un tipo diverso. Mi è stato detto che un'espressione lambda può ottenere lo stesso risultato.

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

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

Qualsiasi aiuto sarebbe apprezzato. Sono nuovo di Lambda e Linq grazie, s


@mmcrae questa domanda è più recente di questa
Andy Wiesendanger il

Risposte:


312

Prova quanto segue

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

Questo sta usando una combinazione di Lambdas e LINQ per ottenere la soluzione. La funzione Seleziona è un metodo di stile di proiezione che applicherà il delegato passato (o lambda in questo caso) a ogni valore nella raccolta originale. Il risultato verrà restituito in un nuovo IEnumerable<TargetType>. La chiamata .ToList è un metodo di estensione che lo convertirà IEnumerable<TargetType>in a List<TargetType>.


Esiste un modo per farlo senza una realizzazione concreta per TargetType? Ho finito con qualcosa del genere: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList();dove l'obiettivo era ottenere un oggetto del tipoList<ISearchEntity>
Aaron Newton,

220

Se si sa che si desidera convertire da List<T1>a List<T2>allora List<T>.ConvertAllsarà leggermente più efficiente di Select/ ToListperché conosce l'esatta dimensione di iniziare con:

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

Nel caso più generale quando si conosce la fonte solo come IEnumerable<T>, usare Select/ ToListè la strada da percorrere. Si potrebbe anche sostenere che in un mondo con LINQ, è più idiomatico per cominciare ... ma vale la pena almeno essere consapevoli ConvertAlldell'opzione.


1
all'inizio non pensavo di poterlo fare, perché avevo a che fare con un ienumerable (per l'elenco dei sorgenti e non fornisce un'opzione convertall) quindi ho chiamato .ToList () su di esso e ora sto provando convertall - i mi piace meglio che inserire un 'dove' non filtrante
Stratton,

2
Perché avresti bisogno di un dove? Se hai solo, IEnumerable<T>basta chiamare Selecte ToListsecondo la risposta di Jared.
Jon Skeet,

Per altri neofiti come me, puoi anche chiamare un metodo comex => buildTargetType(x)
Snekse,

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

1
Cos'è questa sintassi? Questo non riassembla un lambda. Qualche collegamento alla documentazione sarebbe apprezzato. Grazie, però, qui funziona bene
Pierre de LESPINAY,

L'argomento di ConvertAll è un normale lambda C #, giusto?
avl_sweden,

1
sembra carino, ma ha bisogno di un po 'di contesto su quando (o se) può essere usato. L'ho appena provato e stavo ottenendo cannot cast expressionun'eccezione
Collin M. Barrett il

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

5
-1 questo funzionerebbe solo se il casting fosse possibile e nel caso dei PO sembra essere così.
Mike Zboray,

Funziona come previsto! necessario per convertire Elenco <oggetto> in Elenco <Tipo realtà>
Elo

20

Credo che qualcosa del genere dovrebbe funzionare:

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

1
Devi aggiungere un .ToList()alla fine, altrimenti questo fornirà semplicemente un IEnumerable.
MattD,

10

Ecco un semplice esempio ..

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

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

1
Fantastico ... esattamente quello che stavo cercando! Beh, non proprio esattamente ... Volevo solo una proprietà di ciascun elemento nell'elenco, ma mi hai dato la sintassi di lamba senza dover scorrere troppo lontano. ;)
errore del

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

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

3

Supponiamo di avere più proprietà che si desidera convertire.

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

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 Linqlinea è più morbida! ;-)


0

Se devi usare una funzione per trasmettere:

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

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

Dove si trova la mia funzione personalizzata:

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

0

per classe di tipo simile.

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


Grazie mille. È costoso per il server e non è secondo le migliori pratiche, ma funziona magnificamente. L'ho usato per convertire le prime classi del database EF quando di conseguenza più procedure restituiscono le stesse 5 colonne, solo per diverse "clausole where" nelle procedure. So che avrei dovuto creare il tipo di tabella nel database, ma non ero il progettista di quel ..
jo1storm

-1

Se i tipi possono essere lanciati direttamente, questo è il modo più pulito per farlo:

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

Se non è possibile eseguire il cast diretto dei tipi, è possibile mappare le proprietà dal tipo originale al tipo di destinazione.

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

-1

Prenderemo in considerazione il primo tipo di elenco come String e vogliamo convertirlo in tipo intero di elenco.

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

Aggiungi valori nell'elenco originale.

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

Crea un elenco di destinazione di tipo intero

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

Stampa i valori dell'elenco usando forEach:

    targetLambdaList.forEach(System.out::println);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.