使用lambda表达式将对象列表从一种类型转换为另一种类型


224

我有一个foreach循环,读取一种类型的对象列表并产生另一种类型的对象列表。有人告诉我,lambda表达式可以达到相同的结果。

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

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

任何帮助将不胜感激-我是lambda和linq的新手,谢谢,s


@mmcrae这个问题比这个问题新
Andy Wiesendanger

Answers:


312

尝试以下

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

这是结合使用Lambda和LINQ来实现的。Select函数是一种投影样式方法,它将传入的委托(在本例中为lambda)应用于原始集合中的每个值。结果将以新的形式返回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>
Aaron Newton

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(),现在我正在尝试convertall-我比放在一个没有过滤的“位置”更好
-Stratton

2
为什么需要在哪里?如果你只有IEnumerable<T>那么只需要调用SelectToList按Jared的答案。
乔恩·斯基特

对于像我这样的其他新手,您也可以调用x => buildTargetType(x)
Snekse 2014年

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

1
这是什么语法?这不会装配lambda。一些文档链接将不胜感激。不过,谢谢,它在这里工作得很好
Pierre de LESPINAY 2015年

ConvertAll的参数是常规C#lambda,对吗?
avl_sweden

1
看起来不错,但何时(或是否)可以使用它需要一些上下文。我刚刚尝试过,却遇到了cannot cast expression例外
Collin M. Barrett

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

5
-1仅在可能进行铸造时才起作用,并且在OP中确实如此。
Mike Zboray 2012年

可以正常工作!需要将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
太棒了...正是我想要的!好吧,不完全准确……我只是想要列表中每个Element的属性,但是您无需滚动太远就可以使用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

或使用constructorlinqSelect

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


非常感谢你。对于服务器而言,它就像地狱一样昂贵,并且不是按照最佳实践,而是出色地工作。当多个过程返回相同的5列(仅针对过程中的不同“ where子句”)时,我将其用于转换EF数据库第一类。我知道我应该在数据库上创建表类型,但是我不是数据库表的设计者
。–

-1

如果可以直接转换类型,则这是最干净的方法:

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

如果不能直接转换类型,则可以将属性从原始类型映射到目标类型。

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

-1

我们将考虑将第一个List类型为String并将其转换为List的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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.