简体   繁体   中英

How to convert an IEnumerable<IEnumerable<T>> to a IEnumerable<T>

I have an IEnumerable<IEnumerable<T>> collection that I want to convert to a single dimension collection. Is it possible to achieve this with a generic extension method? Right now I'm doing this to achieve it.

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

//For each collection in the combinated results collection
foreach (var combinatedValues in combinatedResults)
{
    List<string> subCombinations = new List<string>();
    //For each value in the combination collection
    foreach (var value in combinatedValues)
    {

        if (value > 0)
        {
            subCombinations.Add(value.ToString());
        }
    }
    if (subCombinations.Count > 0)
    {
       filteredCombinations.Add(String.Join(",",subCombinations.ToArray()));
    }
}

If it's not possible to get a generic solution, how can I optimize this in an elegant fashioned way.

You can use the Enumerable.SelectMany extension method for this.

If I read your code correctly, the code for that would be:

var filteredCombinations = combinatedResults.SelectMany(o => o)
    .Where(value => value > 0)
    .Select(v => v.ToString());

Edit : As commented, the above code is not joining each element of the subsets to a string, as the original code does. Using the built-in methods, you can do that using:

var filteredCombinations = combinatedResults
     .Where(resultSet => resultSet.Any(value => value > 0)
     .Select(resultSet => String.Join(",",
         resultSet.Where(value => value > 0)
                  .Select(v => v.ToString()).ToArray()));

I would personally use Enumerable.SelectMany , as suggested by driis .

However, if you wanted to implement this yourself, it would be much cleaner to do:

IEnumerable<T> MakeSingleEnumerable<T>(IEnumerable<IEnumerable<T>> combinatedResults)
{
    foreach (var combinatedValues in combinatedResults) {
         foreach (var value in combinatedValues)
              yield return value;
    }
}

Here you go:

var strings = combinedResults.Select
    (
        c => c.Where(i => i > 0)
        .Select(i => i.ToString())
    ).Where(s => s.Any())
    .Select(s => String.Join(",", s.ToArray());

You asked two different questions. The one you described in the title is already answered by drilis.

But your example code is a different problem. We can refactor it in stages. Step 1, build the subCombinations list using some Linq:

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

//For each collection in the combinated results collection
foreach (var combinatedValues in combinatedResults)
{
    var subCombinations = combinatedValues.Where(v => v > 0)
                                          .Select(v => v.ToString())
                                          .ToList();

    if (subCombinations.Count > 0)
       filteredCombinations.Add(string.Join(",",subCombinations.ToArray()));
}

Now the outer loop, leaving us with just this:

var filteredCombinations = combinatedResults
    .Select(values => values.Where(v => v > 0)
                            .Select(v => v.ToString())
                            .ToArray())
    .Where(a => a.Count > 0)
    .Select(a => string.Join(",", a));

使用linq SelectMany

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