简体   繁体   中英

Using C# LINQ to concat a filtered List<object> to List<string>

This is probably easy for someone more experienced with LINQ and the Lambda expressions in C#. I'm just starting out with them, so I must be missing something.

I have a custom object like this:

public class BusinessName {
    public string Name { get; set; }
    public string Type { get; set; }
}

Then, I have a list of these objects:

List<BusinessName> businessNames = new List<BusinessName>();

I want to convert this into a list of string with the Name property of the BusinessName object:

List<string> names = new List<string>();

Obviously, I could do this:

foreach (BusinessName name in businessNames) {
    names.Add(name.Name);
}

But, I want to try using the lambda expressions with LINQ so that I can put this into a one liner.

So, I tried:

names.AddRange(businessNames.Select(item => item.Name));

This works as expected, but is much slower than the foreach loop by 2x. I suspect this is because it's iterating the list twice, unlike the foreach loop.

So, I started looking for an alternative. I found Concat() but couldn't figure out how it was any different than AddRange() .

Does anyone know a way to do this in one pass with LINQ?

If names is empty, what you're meant to do is this:

var names = businessNames.Select(item => item.Name).ToList();

Another option is to use the List<T> 's ConvertAll method, like so:

var names = buisnessNames.ConvertAll(item => item.Name);

However, if it may be not empty, you'd need to use an if statement too:

var names = new List<string>();
//some code
if (names.Any())
    names.AddRange(/*your selected method*/);
else
    names = //your selected method;

因为businessNames是List,所以可以使用List.ForEach:

businessNames.ForEach(bn => names.Add(bn.Name));

You could try making your foreach solution a bit quicker by expanding List<string> capacity manually before the loop:

var newList = new List<string>(names.Count + businessNames.Count);
newList.AddRange(names); // will perform `Array.Copy` on underlying array //

foreach (BusinessName name in businessNames) {
    newList.Add(name.Name);
}

names = newList; // replace old list with a new one //

When you call Add there is a check performed, to make sure that underlying array is big enough to contain one more element. If it's not, it is expanded by creating new one, copying all values and replacing it. When you add a lot of items it may happen multiple times. It may be quicker to just help and set initial List<string> capacity to required number of items.

public class BusinessName {
    public string Name { get; set; }
    public string Type { get; set; }
}
void Main()
{
    List<BusinessName> businessNames = new List<BusinessName>();
    List<string> names = new List<string>();
    names=names.Concat(businessNames.Select(b=>b.Name)).ToList();
}
List<string> names = (from b in buisnessNames select b.Name).ToList();

或类似的东西...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM