преобразовать список объектов из одного типа в другой с помощью лямбда-выражения

224

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

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

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

Любая помощь будет оценена - я новичок в лямбда и Линк спасибо, с

Stratton
источник
@mmcrae этот вопрос новее, чем этот
Энди Визендангер

Ответы:

312

Попробуйте следующее

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

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

JaredPar
источник
Есть ли способ сделать это без конкретной реализации для 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
сначала я не думал, что смогу это сделать, потому что я имел дело с ienumerable (для списка источников, и он не предоставляет опцию convertall), поэтому я вызвал .ToList () для него, и теперь я пытаюсь конвертировать - я нравится это лучше, чем вставлять нефильтрующее «где»
Stratton
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>());
Pranav
источник
5
-1 это сработало бы только в том случае, если приведение было возможно, а в случае ОП это действительно так.
Майк Зборай
Работает как положено! необходимо преобразовать List <object> в List <RealType>
Elo
20

Я считаю, что-то вроде этого должно работать:

origList.Select(a => new TargetType() { SomeValue = a.SomeValue});
Энди Уайт
источник
1
Вам нужно добавить .ToList()в конце, иначе это просто предоставит IEnumerable.
MattD
10

Вот простой пример ..

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

List<string> s = c.Select(x => x.ToString()).ToList();
Ян П
источник
1
Круто ... именно то, что я искал! Ну, не совсем точно ... Я просто хотел, чтобы свойство каждого элемента в списке, но вы дали мне синтаксис lamba без необходимости прокручивать слишком далеко. ;)
извиняюсь
7
var list1 = new List<Type1>();
var list2 = new List<Type2>();

list1.ForEach(item => list2.Add(new Type2() { Prop1 = value1 }));
Крис Арнольд
источник
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();
}
jaimenino
источник
0

для класса схожего типа.

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

Арун Соланки
источник
Большое спасибо. Это чертовски дорого для сервера и не соответствует передовым практикам, но работает великолепно. Я использовал его для преобразования первых классов базы данных EF, когда несколько процедур возвращают в результате одни и те же 5 столбцов, только для разных «выражений where» в процедурах. Я знаю, что должен был сделать табличный тип в базе данных, но я не был дизайнером этого ..
jo1storm
-1

Если типы можно напрямую приводить, это самый чистый способ сделать это:

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

Если типы не могут быть напрямую приведены, то вы можете сопоставить свойства из оригинального типа целевому типу.

var target = yourList.ConvertAll(x => new TargetType { SomeValue = x.SomeValue });
Айо Адесина
источник
-1

Мы рассмотрим первый тип списка как String и хотим преобразовать его в тип списка типа Integer.

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);
Гарима Гарг
источник