285

I have a foreach loop reading a list of objects of one type and producing a list of objects of a different type. I was told that a lambda expression can achieve the same result.

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

foreach(OrigType a in origList) {
    targetList.Add(new TargetType() {SomeValue = a.SomeValue});
}
1
  • @mmcrae that question is newer than this one Commented Nov 17, 2016 at 19:26

14 Answers 14

411

Try the following

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

This is using a combination of Lambdas and LINQ to achieve the solution. The Select function is a projection style method which will apply the passed in delegate (or lambda in this case) to every value in the original collection. The result will be returned in a new IEnumerable<TargetType>. The .ToList call is an extension method which will convert this IEnumerable<TargetType> into a List<TargetType>.

Sign up to request clarification or add additional context in comments.

2 Comments

Is there a way to do this without having a concrete implementation for TargetType? I've ended up with something like this: List<ISearchEntity> results = myIQueryable.Select(x => (ISearchEntity) new TargetType { MyField = "Field value is " + x.TargetField }).ToList(); where the goal was to get an object of type List<ISearchEntity>
How can this be adapted to work with an anonymous type as a target type? Is that possible?
268

If you know you want to convert from List<T1> to List<T2> then List<T>.ConvertAll will be slightly more efficient than Select/ToList because it knows the exact size to start with:

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

In the more general case when you only know about the source as an IEnumerable<T>, using Select/ToList is the way to go. You could also argue that in a world with LINQ, it's more idiomatic to start with... but it's worth at least being aware of the ConvertAll option.

4 Comments

at first i didn't think i could do this, because i was dealing with an ienumerable (for the source list and it doesnt provide a convertall option) so i called .ToList() on it and now i'm trying convertall - i like it better than putting in a non-filtering 'where'
Why would you need a where? If you've only got IEnumerable<T> then just call Select and ToList as per Jared's answer.
For other newbies like me, you can also call a method like x => buildTargetType(x)
Best One Liner!
73
var target = origList.ConvertAll(x => (TargetType)x);

4 Comments

What is this syntax ? This does not ressemble a lambda. Some documentation link would be appreciated. Thanks though, it works fine here
The argument to ConvertAll is a regular C# lambda, right?
looks nice, but needs some context around when (or if) it can be used. I just tried it and was getting a cannot cast expression exception
Savage cast... please don't or explain with a real example and comment what the user needs to adapt
40
List<target> targetList = new List<target>(originalList.Cast<target>());

3 Comments

-1 this would only work if casting was possible and in the OPs case it does appear be so.
Works as expected ! needed to convert List<object> to List<RealType>
Note that this answer only works if TargetType is a base type of OrigType. Can be simplified to ... = originalList.Cast<TargetType>().ToList();
22

I believe something like this should work:

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

1 Comment

You need to add a .ToList() at the end, otherwise this will simply provide an IEnumerable.
12

Here's a simple example..

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

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

1 Comment

Awesome... exactly what I was looking for! Well not quite exactly... I just wanted a property of each Element in the list, but you gave me the lamba syntax without having to scroll too far. ;)
7
var list1 = new List<Type1>();
var list2 = new List<Type2>();

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

Comments

3

Assume that you have multiple properties you want to convert.

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

Comments

3

Or with a constructor & linq with 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();  

The Linq line is more soft! ;-)

Comments

1

If you need to use a function to cast:

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

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

Where my custom function is:

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

1 Comment

It's possible to shorten even further, list2 = list1.ConvertAll(myConvertFuntion);
1

for similar type class.

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

1 Comment

Thank you very much. It is expensive as hell for server and it is not according to best practices, but works splendidly. I used it for converting EF database first classes when multiple procedures return the same 5 columns as a result, only for different "where clauses" in the procedures. I know I should have made table type on the database, but I wasn't the designer of that..
0

If the types can be directly cast this is the cleanest way to do it:

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

If the types can't be directly cast then you can map the properties from the orginal type to the target type.

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

Comments

0

If casting when mapping from one list to another is required, from convertall, you can call a function to test the casting.

public int StringToInt(String value)
        {
            try
            {
                return Int32.Parse(value);
            }
            catch (Exception ex)
            {
                return -1;
            }
        }
        [Fact]
        public async Task TestConvertAll()
        { 
            List<String> lstString = new List<String>{"1","2","3","4","5","6","7","8","9","10" };

            List<int> lstInt = lstString.ConvertAll(new Converter<String, int>(StringToInt));
            foreach (var item in lstInt)
            {
                output.WriteLine("{0}", item);
            }
            if (lstInt.Count()>0) {
                Assert.True(true);
            }
        }

Comments

-1

We will consider first List type is String and want to convert it to Integer type of List.

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

Add values in the original List.

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

Create target List of Integer Type

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

Print List values using forEach:

    targetLambdaList.forEach(System.out::println);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.