good-to-know
good-to-know

Reputation: 742

How to change multiple foreach iteration to single LINQ?

emailAddresses is the List of strings. notificationRequest is the class has the field RequestXml (type is XDocument).

RequestXml will be like:

<root>
    <result>
        <SUBMITTERALIAS>[email protected]</SUBMITTERALIAS>
    </result>
    <result>
        <SUBMITTERALIAS>[email protected]</SUBMITTERALIAS>
    </result>
</root>

I want to get all the email address in the SUBMITTERALIAS to be saved in the string list. So I wrote the following piece of code. I did work and does the job.

var emailAddresses = new List<string>();

foreach (var request in notificationRequest)
{
    foreach (var email in request.RequestXml.Descendants("SUBMITTERALIAS"))
    {
        emailAddresses.Add(email.Value);
    }
}

I would like to use single line LINQ code instead of above foreach. Any ideas?

Upvotes: 0

Views: 228

Answers (4)

Charles Mager
Charles Mager

Reputation: 26233

You need to flatten your query so that just it returns a sequence of email addresses:

var emailAddresses = 
    from request in notificationRequest
    from email in request.RequestXml.Descendants("SUBMITTERALIAS")
    select email.Value;

And if you actually do need it to be a list:

var emailAddressList = emailAddresses.ToList();

An OO approach might be to create an EmailAddresses() method in request:

public IEnumerable<string> EmailAddresses()
    => RequestXml.Descendants("SUBMITTERALIAS").Select(x => x.Value);

And change your query to use that:

var emailAddresses = notificationRequest.SelectMany(x => x.EmailAddresses());

Upvotes: 0

Tolga Evcimen
Tolga Evcimen

Reputation: 7352

This should do it:

var emailAddresses = notificationRequest.
    /// flatten the list of descendats list to email list
    SelectMany(request => request.RequestXml.Descendants("SUBMITTERALIAS")).
    /// select the value of the email element
    Select(email => email.Value).
    /// convert it to a List
    ToList();

Upvotes: 2

ironhide391
ironhide391

Reputation: 595

request.RequestXml.Descendants("SUBMITTERALIAS").ToList().ForEach(x => emailAddresses.Add(x.Value));

Upvotes: 0

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43946

If you want to add the address to another list you can flatten the lists with SelectMany and use AddRange:

emailAddresses.AddRange(notificationRequest.SelectMany(request =>
                  request.RequestXml.Descendants("SUBMITTERALIAS"))
                  .Select(email => email.Value));

If you create a complete new list you can simply call it like that:

emailAddresses = notificationRequest.SelectMany(request =>
                  request.RequestXml.Descendants("SUBMITTERALIAS"))
                  .Select(email => email.Value).ToList();

Upvotes: 2

Related Questions