Home > OS >  convert IEnumerable<double> to double
convert IEnumerable<double> to double

Time:10-23

I need return sum of elements with odd indexes in the array of doubles This is my code:

 public static double EvaluateSumOfElementsOddPositions(double[] inputData)
    {
        
        var sum = inputData
            .Select((v, i) => new { Group = (i % 2 != 0), Value = v })
            .GroupBy(x => x.Group)
            .Select(g => g.Sum(y => y.Value));
        return sum ;
    }

But I have a mistake: Can't implicitly convert IEnumerable to double. I don't know how I can deal with that... Help, please!

CodePudding user response:

What you are looking for is something like:

public static double EvaluateSumOfElementsOddPositions(double[] inputData)
{
    return inputData
        .Where((data, index) => index % 2 != 0)
        .Sum();
}

You don't need to group the elements if you are not going to use elements at even indices.

CodePudding user response:

Although it is a nice exercise to try to do this using LINQ, it is not very efficient.

GroupBy will create a Dictionary<Tkey, ICollection<TResult>>, or to be more precise: a Lookup Table. For every element, it will extract the key and the TResult. For ever element it will check if the Key is in the Lookup Table.

  • If not, it will put the TResult in a new ICollection<TResult> and add the Key and the collection to the table.
  • It the Key is in the table it will add the TResult to the end of the collection.

This is quite a lot of work, while in fact the only thing you want is:

public static IEnumerable<double> ToEveryOtherDouble(this IEnumerable<double> doubles)
{
    bool everyOther = false;
    // will return elements with index 1, 3, 5, ...
    // start with true if you want 0, 2, 4, ...
   
    foreach (double d in doubles)
    {
        if (everyOther)
            yield return d;
        everyOther = !everyOther;
    }

Usage:

IEnumerable<double> inputData = ....
double sum = inputData.ToEveryOtherDouble().Sum();

If you insist on using LINQ, make two groups: a group containing doubles with the even indexes, and a group containing doubles with the odd indexes.

So Key of the group: i % 2

double sum = inputData.Select( (d, index) => new
{
    Index = index,
    Value  = d,
})
.GroupBy(x => x.Index % 2,   // keySelector: groups with key 0 and key 1

    // parameter elementSelector: specify the elements of each group
    x => x.Value)            // as elements of the group, we only need the double

Result of the GroupBy: two groups. A group with key 0 and a group with key 1. The group with key 0 has as elements the doubles at even indexes, the group with key 1 has as elements the doubles at odd indexes.

Continuing the LINQ: if you want only the even indexes:

.Where(group => group.Key == 0).Sum();

Conclusion

The choice is yours: which one is easier to read, reuse, maintain and unit test:

double sum = inputData.Select( (d, index) => new
{
    Index = index,
    Value  = d,
})
.GroupBy(x => x.Index % 2, x => x.Value)
.Where(group => group.Key == 0)
.Sum();

Or:

double sum = inputData.ToEveryOtherDouble().Sum();
  • Related