Reputation: 742
I have a list of strings like:
[email protected]
[email protected]
[email protected];[email protected];[email protected]
[email protected]
[email protected]
I would like to want it as:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
So I wrote the code below and it works as expected.
foreach (var email in emailAddressesOnRequest)
{
if (!string.IsNullOrEmpty(email) && email.Contains(';'))
{
emailAddressesOnRequest.AddRange(email.Split(';').ToList());
emailAddressesOnRequest.Remove(email);
}
}
Is there any way to simply it to LINQ ForEach?
Upvotes: 1
Views: 379
Reputation: 37299
What you are looking for is to iterate through the collection and for each item to return an item of a different kind. For that use Select
.
Because in your case you possibly want to return from each item a collection of items, and don't want to have them in nested collections use SelectMany
on the result of the Split(';')
method.
List<string> values = new List<string>
{
"[email protected]",
"[email protected]",
null,
"[email protected]; mnop @domain.com; qrst @domain.com",
"[email protected]",
"[email protected]"
};
var result = values.Where(value => !string.IsNullOrWhiteSpace(value))
.SelectMany(value => value.Split(';')).ToList();
And in query syntax:
var result = (from value in values
where !string.IsNullOrWhiteSpace(value)
from email in value.Split(';')
select email).ToList();
Upvotes: 5
Reputation: 30454
What helped me a lot to understand ling was The standard LINQ operators
If you split each string into substrings by semicolon, you get a collection of string sequences, or an IEnumerable<IEnumerable<string>>
The IEnumareable
extension function to convert them to an IEnumerable<string>
is Enumerable.SelectMany
. When iterating over a SelectMany
it is like you do a nested foreach:
List<string[]> listOfStringArrays = ...
List<string> outputList = new List<string>();
foreach (string[] stringArray in listOfStringArrays)
{
foreach (string str in stringArray)
{
outputList.Add(str);
}
}
In your example the inner foreach is done using AddRange
.
Using Select
and Split
you convert your collection of strings to a sequence of string sequences. SelectMany
will make it a sequence of strings:
IEnumerable<string> myInputStrings = ...
IEnumerable<string> outputStrings = inputStrings
.Select(inputString => inputString.Split(';'))
.SelectMany(splitResult => splitResult);
The Select will take each of the inputStrings, and split them by semicolon. The output is a string array, which implements IEnumerable<string>
, even if your input didn't have a semicolon.
The SelectMany
concatenates every string sequence of you sequence of string sequences. The result is one sequence of strings.
To convert to array or list use ToArray()
or ToList()
.
Upvotes: 1
Reputation: 7036
var query = from line in emailAddressesOnRequest
where !String.IsNullOrEmpty(line)
from email in line.Split(';')
select email;
Upvotes: 1