lambda ifadesini kullanarak bir nesne listesini bir türden diğerine dönüştürme


226

Bir tür nesnelerin listesini okuma ve farklı türdeki nesnelerin bir listesini üreten bir foreach döngü var. Bana lambda ifadesinin aynı sonucu elde edebileceği söylendi.

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

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

Herhangi bir yardım mutluluk duyacağız - lambda ve linq için yeniyim teşekkürler, s


@mmcrae bu soru bundan daha yeni
Andy Wiesendanger

Yanıtlar:


313

Takip etmeyi dene

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

Bu, çözümü elde etmek için bir Lambdas ve LINQ kombinasyonu kullanıyor. Seç işlevi, iletilen temsilci (veya bu durumda lambda) orijinal koleksiyondaki her değere uygulayacak bir projeksiyon stili yöntemidir. Sonuç yeni olarak döndürülecektir IEnumerable<TargetType>. .ToList çağrısı, bunu IEnumerable<TargetType>bir List<TargetType>.


Bunun somut bir uygulaması olmadan bunu yapmanın bir yolu var mı TargetType? Böyle bir şeyle sonuçlandım: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList();hedefin tür bir nesne elde etmektiList<ISearchEntity>
Aaron Newton

220

Eğer varsa bilmek sizden dönüştürmek istediğiniz List<T1>için List<T2>o zaman List<T>.ConvertAllbiraz daha verimli olacaktır Select/ ToListo ile başlamak tam boyutunu bildiği için:

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

Daha genel bir durumda, kaynağı yalnızca bir olarak bildiğinizde IEnumerable<T>, Select/ kullanmanın ToListyolu vardır. Sen olabilir ayrıca LINQ ile bir dünyada, bu başlamak daha deyimsel olduğunu iddia ... ama en azından 's değerinde farkında ConvertAllseçeneği.


1
ilk başta ben ienumerable (kaynak listesi için ve bu bir convertall seçeneği sağlamaz) ile ilgili çünkü ben bunu yapabileceğini düşünmüyordu bu yüzden .ToList () denilen ve şimdi ben convertall çalışıyorum - i filtrelemeyen bir 'nereye' koymaktan daha iyi gibi
Stratton

2
Neden bir yere ihtiyacınız var? Yalnızca var ise IEnumerable<T>o zaman sadece aramak Selectve ToListJared'in Yanıt başına kadar.
Jon Skeet

Benim gibi diğer yeni başlayanlar için de şöyle bir yöntem çağırabilirsinizx => buildTargetType(x)
Snekse

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

1
Bu sözdizimi nedir? Bu bir lambda'yı yeniden birleştirmez. Bazı dokümantasyon bağlantıları takdir edilecektir. Teşekkürler olsa da, burada iyi çalışıyor
Pierre de LESPINAY

ConvertAll argümanı normal bir C # lambda, değil mi?
avl_sweden

1
hoş görünüyor, ancak ne zaman (ya da eğer) kullanılabileceği konusunda bir bağlam gerekiyor. Ben sadece denedim ve bir cannot cast expressionistisna alıyordu
Collin M. Barrett

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

5
-1 Bu yalnızca döküm mümkün olduğunda işe yarar ve OP durumunda bu böyle görünür.
Mike Zboray

Beklendiği gibi çalışıyor! <object> Listesini <RealType> Listesine dönüştürmek için gerekli
Elo

20

Böyle bir şeyin çalışması gerektiğine inanıyorum:

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

2
.ToList()Sonunda bir eklemeniz gerekir , aksi takdirde bu yalnızca bir IEnumerable sağlar.
MattD

10

İşte basit bir örnek ..

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

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

1
Awesome ... tam olarak ne aradığını! Tam olarak değil ... Listedeki her bir Elemanın bir özelliğini istedim, ancak çok fazla kaydırmak zorunda kalmadan bana lamba sözdizimini verdin. ;)
erroric

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

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

3

Dönüştürmek istediğiniz birden çok özelliğiniz olduğunu varsayalım.

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

Veya constructor& linqile 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();  

LinqÇizgi daha yumuşaktır! ;-)


0

Yayınlamak için bir işlev kullanmanız gerekiyorsa:

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

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

Özel işlevim nerede:

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

0

benzer tip sınıf için.

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


Çok teşekkür ederim. Sunucu için cehennem kadar pahalı ve en iyi uygulamalara göre değil, görkemli çalışıyor. Birden çok yordam sonuç olarak aynı 5 sütun döndürdüğünde EF veritabanı birinci sınıfları dönüştürmek için kullandım, yalnızca yordamlarda farklı "nerede yan tümceleri" için. Ben veritabanında tablo türü yapmalıydım biliyorum, ama bunun tasarımcı değildi ..
jo1storm

-1

Türler doğrudan dökülebilirse, bunu yapmanın en temiz yoludur:

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

Türler doğrudan yayınlanamıyorsa, özellikleri orijinal türden hedef türe eşleyebilirsiniz.

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

-1

İlk Liste türünün Dize olduğunu ve bunu Tamsayı Liste türüne dönüştürmek isteyeceğiz.

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

Orijinal Listeye değerler ekleyin.

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

Hedef Tamsayı Türü Listesi Oluştur

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

ForEach kullanarak Liste değerlerini yazdır:

    targetLambdaList.forEach(System.out::println);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.