Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected results in Linq query always + 1

Tags:

c#

linq

I have the below code and I'm expecting a different result.
I have excepted that following result: 100 ,110 ,120 , 200, 500

  using System;
  using System.Collections.Generic;
  using System.Linq;

  namespace ConsoleApplication11
  {
    public class Program
    {
      static void Main(string[] args)
      {
        var values = new List<int> { 100, 110, 120, 200 , 500 };

        //  In my mind the result shall be like (100,0) => 100 + 0 = 100 
        //  In my mind the result shall be like (110,0) => 110 + 0 = 110 etc. 
        var sumLinqFunction = new Func<int, int, int>((x, y) => x + y);
        var outputs = values.Select(sumLinqFunction);

        foreach (var o in outputs)
          Console.WriteLine(o);
      }
    }
  }

Console output (real result)

100
111
122
203
504

I'm wondering now about this +1 from where came?

like image 366
Bassam Alugili Avatar asked Sep 17 '13 14:09

Bassam Alugili


4 Answers

That is because the second parameter of the Select() method overload you are using is just the index of the item in the input set.

EDIT:

As @user7116 suggested, you may want to simply include in your projection function a value from the outer scope:

int y = 0;
var results = values.Select(x => x + y);
like image 101
Efran Cobisi Avatar answered Oct 15 '22 04:10

Efran Cobisi


Your Func, sumLinqFunction, is expecting two parameters, adding them up and then returning their result.

When you are using that in Select statement it is like:

var outputs = values.Select((x, y) => x + y);

which uses the overload of Select which expects the second parameter to be index.

The first argument to selector represents the element to process. The second argument to selector represents the zero-based index of that element in the source sequence. This can be useful if the elements are in a known order and you want to do something with an element at a particular index, for example. It can also be useful if you want to retrieve the index of one or more elements.

So y starts with 0. With each iteration the index (y) moves to next element, thus you see the increment of +1.

To explain it a bit more, you can modify your Func to display current values of x and y like:

var sumLinqFunction = new Func<int, int, int>((x, y) =>
    {
        Console.WriteLine("x: {0} , y: {1}", x, y);
        return x + y;
    });
var outputs = values.Select(sumLinqFunction).ToList(); //iterate to get the results.

This would give you:

x: 100 , y: 0
x: 110 , y: 1
x: 120 , y: 2
x: 200 , y: 3
x: 500 , y: 4

For your comment:

I need to call the select with the default value 0 and not the index!

Then instead of having a Func you can simply do:

int y = 0;
var outputs = values.Select(r => r + y);
like image 39
Habib Avatar answered Oct 15 '22 06:10

Habib


You are using the wrong Select overload.

It just adds the index to the current value:

100 + 0
110 + 1
120 + 2
200 + 3
500 + 4

You don't need a query for the expected output.

var values = new List<int> { 100, 110, 120, 200 , 500 };

foreach (var o in outputs)
      Console.WriteLine(o);
like image 38
Ufuk Hacıoğulları Avatar answered Oct 15 '22 05:10

Ufuk Hacıoğulları


Check the definition of the Select overload you are invoking:

http://msdn.microsoft.com/en-us/library/bb534869.aspx

In this case you are invoking this overload:

public static IEnumerable<TResult> Select<TSource, TResult>(
    this IEnumerable<TSource> source,
    Func<TSource, int, TResult> selector
)

whereby selector is (emphasis mine)

A transform function to apply to each source element; the second parameter of the function represents the index of the source element.

So your selector lambda is returning the number at the current array index PLUS the array index, hence

(x, y) => x + y

(100,0) =>100+0

(110,1) =>110+1

(120,2) =>120+2

(200,3) =>200+3

(500,4) =>500+4

like image 25
Stephen Byrne Avatar answered Oct 15 '22 05:10

Stephen Byrne