перетворити список об’єктів одного типу в інший, використовуючи лямбда-вираз


224

У мене є цикл foreach, який читає список об'єктів одного типу та створює список об'єктів іншого типу. Мені сказали, що лямбда-вираз може досягти такого ж результату.

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

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

Будь-яка допомога буде вдячна - я новачок у лямбдах та linq спасибі, s


@mmcrae це питання новіше, ніж це
Енді Візендангер

Відповіді:


312

Спробуйте наступне

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

Для досягнення цього рішення використовується комбінація лямбдасів та LINQ. Функція Select - це метод стилю проекції, який застосовуватиме переданий делегат (або в даному випадку лямбда) до кожного значення в оригінальній колекції. Результат буде повернутий по-новому IEnumerable<TargetType>. Виклик .ToList - це метод розширення, який перетворить це IEnumerable<TargetType>в List<TargetType>.


Чи є спосіб це зробити, не маючи конкретної реалізації TargetType? Я закінчив щось подібне: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList();де метою було отримати об’єкт типуList<ISearchEntity>
Аарон Ньютон

220

Якщо ви знаєте, що хочете перетворити з List<T1>того, List<T2>то List<T>.ConvertAllбуде трохи ефективнішим, ніж Select/ ToListтому, що він знає точний розмір для початку:

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

У більш загальному випадку, коли ви знаєте лише про джерело як про IEnumerable<T>, використовуйте Select/ ToList- це шлях. Ви могли б також стверджувати , що в світі з допомогою LINQ, це більш ідіоматичних почати з ... але це варто , по крайней мере усвідомлюючи ConvertAllваріант.


1
спочатку я не думав, що можу це зробити, тому що я мав справу з безліччю (для списку джерел, і він не надає варіант для конвертації), тому я назвав .ToList () на ньому, і тепер я намагаюся конвертувати - я подобається це краще, ніж ставити без фільтру "куди"
Страттон

2
Навіщо тобі потрібно де? Якщо у вас є тільки IEnumerable<T>тоді, просто зателефонуйте Selectі ToListвідповідно до відповіді Джареда.
Джон Скіт

Для інших новачків, як я, ви також можете зателефонувати за таким способомx => buildTargetType(x)
Snekse

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

1
Що це за синтаксис? Це не відновлює лямбда. Деякі посилання на документацію будуть вдячні. Спасибі, хоча, тут добре працює
Pierre de LESPINAY

Аргумент ConvertAll - це звичайна лямбда C #, правда?
avl_sweden

1
виглядає приємно, але потребує певного контексту, коли (або якщо) його можна використовувати. Я просто спробував це і отримав cannot cast expressionвиняток
Колін М. Барретт

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

5
-1 це буде працювати лише в тому випадку, якщо кастинг був можливим, а у випадку з ОП це здається так.
Майк Зборай

Працює як очікувалося! необхідний для перетворення списку <об’єкт> у список <RealType>
Ело,

20

Я вважаю, що щось подібне має спрацювати:

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

1
Вам потрібно додати в .ToList()кінці, інакше це просто забезпечить IEnumerable.
МтД

10

Ось простий приклад ..

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

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

1
Дивовижно ... саме те, що я шукав! Ну не зовсім точно ... Я просто хотів властивості кожного Елементу у списку, але ти дав мені синтаксис "ламба", не надто сильно прокручуючи. ;)
помилковий


3

Припустимо, що у вас є кілька властивостей, які ви хочете конвертувати.

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

Або з constructor& linqз 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Лінія м'якший! ;-)


0

Якщо вам потрібно використовувати функцію для передачі:

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

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

Де моя спеціальна функція:

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

0

для аналогічних класів типів.

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


Велике спасибі. Це дорого, як пекло для сервера, і не відповідає найкращим практикам, але працює чудово. Я використовував це для перетворення перших класів бази даних EF, коли в результаті декількох процедур повертаються однакові 5 стовпців, лише для різних "де застережень" у процедурах. Я знаю, що я повинен був зробити тип таблиці в базі даних, але я не був дизайнером цього ..
jo1storm

-1

Якщо типи можна безпосередньо надати, це найчистіший спосіб зробити це:

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

Якщо типи неможливо передати безпосередньо, ви можете зіставити властивості від початкового типу до цільового типу.

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

-1

Ми розглянемо перший тип списку - String і хочемо перетворити його в цілий тип списку.

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

Додайте значення в оригінальний Список.

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

Створення цільового списку типу цілого числа

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

Значення списку друку за допомогою forEach:

    targetLambdaList.forEach(System.out::println);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.