6

I haven't been able to find anything on google.

I have this piece of code:

Random r = new Random();
int[] output = Enumerable.Range(0, 11).Select(x => x / 2).OrderBy(x => r.Next()).ToArray();

and I am having trouble actually understanding what each element does.

It generates a range of numbers and elements between 0 and 11. But what does the select(x => x / 2) do ? does it just make pairs of elements,

I know what the whole thing spits out, an array with pairs of numbers, with a single number which has no pair.

but it is a bit above me to fully understand it ?

( is this even okay to ask on here ?? or should I delete the question again ? )

Aditi Parikh
  • 1,522
  • 3
  • 13
  • 34
andrelange91
  • 1,018
  • 3
  • 21
  • 48
  • 2
    Select is basically a mapping: it takes an `IEnumerable`, and a function `Func` and produces an `IEnumerable`. So here it will result in `0, 0, 1, 1, ..., 5, 5. – Willem Van Onsem Aug 24 '17 at 09:02
  • you make a new collection of values with the select where every item from the old collection is divided by 2 – EpicKip Aug 24 '17 at 09:03
  • So it takes a value, splits it in two and "returns" that to the list ? – andrelange91 Aug 24 '17 at 09:04
  • 1
    @andrelange91 No, it divides each value by 2. Remember they're integer values, so each result is truncated. 0.5 would become 0. – Ian Aug 24 '17 at 09:06
  • 1
    [This question is asking about an answer to a question you asked on StackOverflow less than an hour ago](https://stackoverflow.com/questions/45856340/generate-array-with-pairs-of-numbers). **You should ask the person who wrote that answer**. – Flater Aug 24 '17 at 09:07
  • 2
    You should find one of the dozens of LINQ tutorials, or just read the documentation of Enumerable.Select. Simply googling `LINQ Select` will return a *lot* of information – Panagiotis Kanavos Aug 24 '17 at 09:08
  • @PanagiotisKanavos it did return alot of information, too much. so i was unable to understand this specificly did. – andrelange91 Aug 24 '17 at 09:12
  • @Flater According to this: https://meta.stackoverflow.com/questions/284298/is-it-okay-to-ask-a-new-question-about-an-answer Asking a new question in this case is completely fine, right? – Sweeper Aug 24 '17 at 09:30
  • @Sweeper: If it's on a different topic, sure. But he's asking about the main intention of the answer itself, which is inherently on-topic for the previous question. The OP isn't asking "what is division?", he is asking "why would I use division like this **in this case**?" and **this case** is the context of his previous question. Asking a new question makes the question more vague because we lose that context (I recognized the code itself and I had just read the other question, which is dumb luck and coincidence) – Flater Aug 24 '17 at 09:50
  • @Sweeper: My argument is encapsulated by the first comment to the top answer of the Meta post you linked: _"Just beware that **asking for an explanation of someone else's code (What does this code do? How does this work?) is generally off-topic**. One needs to take ownership of the code (compile it, run some test cases, isolate where the behavior is surprising)."_ – Flater Aug 24 '17 at 09:53
  • @Flater i have run the code, i know what the end result is, but i was quite confused about the select statement. and wanted to know more specificly what it did. I did not think that was in que to my earlier question, therefore i made a new one. And it doesn't help that the one who provided the answer in my other question, is quite slow to answer my comments... – andrelange91 Aug 24 '17 at 09:55
  • @andrelange91: When you are provided with an answer (to the earlier question), the answer should be explained in a way that is clear to you. If you require elaboration on why the answer is an appropriate answer, you should ask that of whoever writes the answer (they're the ones who created the answer in the first place, so they are most capable of explaining their own reasoning). This second question is only valid if you can point to _unexpected_ behavior in the code, not when you're asking about the general intention of the code. – Flater Aug 24 '17 at 10:25

4 Answers4

8

It generates a range of numbers and elements between 0 and 11. But what does the select(x => x / 2) do ? does it just make pairs of elements.

No, Select does what in some programming languages is known as map. It is called on an IEnumerable<T> and has as parameter Func<T,U> a function, and it produces an IEnumerable<U> where each element if the given IEnumerable<T> is processes through the function and the result is emitted in the result.

So in this case, it will take a range from 0 to (excluding) 11, and for each of those integers, perform an integer divsion by two:

csharp> Enumerable.Range(0, 11);
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
csharp> Enumerable.Range(0, 11).Select(x => x/2);
{ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5 }

Since:

   { 0/2, 1/2, 2/2, 3/2, 4/2, 5/2, 6/2, 7/2, 8/2, 9/2, 10/2 }
== { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5 }

Later then that IEnumerable<int> is reordered (using the OrderBy) by using pseudo-random numbers (so we shuffle them) and converted into a list.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • giving you the "answer mark" since you explained it in a way i understood first ^^ Edit.. can first do that in 5 min... – andrelange91 Aug 24 '17 at 09:10
  • Why does it exclude the number 11 in that range? The last number in that range specified? It does it for the first, 0, but not the last, 11? – someguy76 Aug 24 '17 at 09:18
  • @someguy76: because `Enumerable.Range(from,to)` includes `from` and excludes `to`. This is the same when generating random integers, etc. It is thus some sort of convention. – Willem Van Onsem Aug 24 '17 at 09:21
  • 1
    I've read another answer below which says it increments the starting number by the last number, or the end of the range. Is that a good way to think about it? – someguy76 Aug 24 '17 at 09:22
  • @someguy76: Well I see `Enumerable.Range(from,to)` as a way to write a `for(int i = from; i < to; i++)` to produce numbers in LINQ. – Willem Van Onsem Aug 24 '17 at 09:27
  • 1
    If you check the documentation it's not "from, to", it's "start, count". So Range(5,2) returns { 5, 6 }. – Owen Pauling Aug 24 '17 at 09:29
  • 1
    @OwenPauling: euh yeah indeed... Java en C# have somehow different conventions on that part :( so sometimes I mix them up... – Willem Van Onsem Aug 24 '17 at 09:30
7
    .Range(0, 11) // generate a sequence of integers starting at 0 and incrementing 11 times (i.e. the values 0 up to and including 10)
    .Select(x => x / 2) // divide each of those values from previous result by 2 and return them
    .OrderBy(x => r.Next()) // then order them randomly using a random number
    .ToArray(); // return the end result as an array
Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
7

Think of Select as doing a transformation to each element of the IEnumerable.

For example, let's say we have a list like this:

0 1 2 3 4 5 6 7 8 9 10

Then we call .Select(x => x / 2), we are saying that for each element x in the list, do the following transformation:

x / 2

We divide each element in the list by two:

Original    Transformation    Result
0           0 / 2             0
1           1 / 2             0
2           2 / 2             1
3           3 / 2             1
4           4 / 2             2
5           5 / 2             2
6           6 / 2             3
7           7 / 2             3
8           8 / 2             4
9           9 / 2             4
10          10 / 2            5

We get

0 0 1 1 2 2 3 3 4 4 5 5
Sweeper
  • 213,210
  • 22
  • 193
  • 313
4

What Select() does is that it evaluates the given expression for every element of the Enumerable it's called on (the original list), and returns a new Enumerable with the results.

For a list:

[2, 4, 6]

it's going to return:

[2/2, 4/2, 6/2]

where / means "division", so the result of the Select() (not the entire LINQ chain) will be:

[1, 2, 3]

Analogously, if your source list is:

words = ["dog", "child", "building"]

And you call:

words.Select(word => word.Length)

you get a list of all the lengths of the strings in the list in order:

[3, 5, 7]
millimoose
  • 39,073
  • 9
  • 82
  • 134
  • So `Enumerable.Range(5, 10, 20).Select(x => x / 5)` should return `(1, 2, 4)` ? – someguy76 Aug 24 '17 at 09:09
  • @someguy76 - You can't give three arguments to `Range()` – millimoose Aug 24 '17 at 09:11
  • 1
    @someguy76 It doesn't do what you seem to think it does. `Range(5, 10)` will generate 10 consecutive numbers starting with 5, i.e. the list `[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]` – millimoose Aug 24 '17 at 09:13
  • So when you select over a range, will it go through all those consecutive numbers and return all of them or just the 2 numbers you specified. This is only for a `Range()` of course – someguy76 Aug 24 '17 at 09:15
  • @someguy76 It will return all of them; then if you call a `Select()` on the range, it will return the result of the select expression for every item in the range. LINQ clauses roughly map to regular imperative statements: `Range(5, 10)` accomplishes more or less the same as `for (int i = 5; i < 5+10; i++) { ... }`. (Where the chained LINQ clauses determine how the body of the loop looks like.) LINQ makes code that would otherwise be a lot of nested blocks "flat." – millimoose Aug 24 '17 at 09:17
  • @someguy76 So for example `Enumerable.Range(5, 10).Select(x => x/2)` corresponds to `for (int x = 5; i < 5+10; i++) { var y = x / 2; ... }` etc. – millimoose Aug 24 '17 at 09:19