I am trying to understand in more detail the use of the Enumerable.Where method. Even though I already understand many details including the use of lambda expression, delegates, predicates and so on, some things make no sense for me and I would appreciate any help.
First I am referring to the explanation from the link below:
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where?view=net-5.0
In the webpage above they have the following code example :
int[] numbers = { 0, 30, 20, 15, 90, 85, 40, 75 };
IEnumerable<int> query =
numbers.Where((number, index) => number <= index * 10);
foreach (int number in query)
{
Console.WriteLine(number);
}
/*
This code produces the following output:
0
20
15
40
*/
My questions are :
Where are the parameters "number" and "index" defined? I understand that the "number" inside the Where is different from the "number" inside the foreach statement.
Why can I change the name of the parameter "number" inside the Where but can't change the name of "index"?
Why does this code produces the output 0, 20, 15, 40? I know the indexes are from 0 to 7.
What is the usage of the left arrow in "number <= index * 10" and what is the official name of this left arrow? (I know the right arrow is to separate input and output in a lambda expression)
Thank you for your attention and support.
Where are the parameters "number" and "index" defined?
They are declared when you write (number, index) => .... (number, index) => is short for (int number, int index) =>. The types can be omitted because they cam be inferred from the signature of Where.
The overload of Where that you are calling is:
public static IEnumerable<TSource> Where<TSource> (
this IEnumerable<TSource> source,
Func<TSource,int,bool> predicate
);
numbers is passed to source, and (number, index) => number <= index * 10 is passed to predicate. The types can be inferred here because from the source parameter, we know TSource is int (since you passed in an int[]), so the type of the predicate parameter must be Func<int,int,bool>.
Func<int,int,bool> represents a function that takes two int and returns a bool. You are supposed to give Where such a function. This is why you are allowed to declare the two parameters (number, index) - these are the parameters for the function that you are passing to Where. As for what the function does...
What is the usage of the left arrow?
It is the "less than or equal to" operator. The function you are passing to Where returns true if number is less than or equal to 10 times the index of the number. You should see why only 0 (at index 0), 20 (at index 2), 15 (at index 3), and 40 (at index 6) are left in the filtered sequence. This should answer your third question too.
Why I can change the name of the parameter "number" inside the Where but can't change the name of "index"?
You can rename just index:
(number, b) => number <= b * 10
or even rename both of them:
(a, b) => a <= b * 10
They are just parameter names after all. Maybe you weren't doing it correctly.
Where are the parameters "number" and "index" defined? I understand that the "number" inside the Where is different from the "number" inside the foreach statement. <
That is from the enumerable extension method Where:
public static System.Collections.Generic.IEnumerable<TSource> Where<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,int,bool> predicate);
That takes takes a Func<source,int,bool> (a function that takes a source element from the collection, an int index and returns a bool).
Why I can change the name of the parameter "number" inside the Where but can't change the name of "index"? <
That represents the index in the enumerable.
Why does this code produces the output 0, 20, 15, 40? I know the indexes are from 0 to 7.
{ 0, 30, 20, 15, 90, 85, 40, 75 }
The where only produces a result ( the number from the list ) when the predicate ( number <= index * 10 ) is true
index 0 number 0: 0 <= 0 * 10 : true
index 1 number 30: 30 <= 1 * 10 : false
index 2 number 20: 20 <= 2 * 10 : true
index 3 number 15: 15 <= 3 * 10 : true
index 4 number 90: 90 <= 4 * 10 : false
index 5 number 85: 85 <= 5 * 10 : false
index 6 number 40: 40 <= 6 * 10 : true
index 7 number 75: 75 <= 7 * 10 : false
What is the usage of the left arrow in "number <= index * 10" and what is the official name of this left arrow? (I know the right arrow is to separate input and output in a lambda expression) <
number is less than or equal to index times ten -- its a less than or equal to comparison returning a bool.
Where are the parameters "number" and "index" defined? I understand that the "number" inside the Where is different from the "number" inside the foreach statement.
Imagine the code looks more like this:
public bool IsElementValid(int number, int index)
{
return number <= index * 10;
}
IEnumerable<int> query = numbers.Where(IsElementValid);
Your code (number, index) => number <= index * 10; is effectively declaring an anonymous method which accepts two parameters: number and index and returns a bool. These are called "lambda expressions" and you can read more about them in the documentation.
You can pass a method here because Where accepts a Func<TElement, int, bool> delegate. A delegate effectively allows you to store one or more methods in a variable. You can read about delegates here.
So now we know that a Func can effectively hold a method, we can digest how Where could work by writing our own:
public List<int> MyOwnWhere(int[] source, Func<int, int, bool> filter)
{
var result = new List<int>();
for (int i = 0; i < source.Length; ++i)
{
if (filter(source[i], i) == true)
{
result.Add(source[i]);
}
}
return result;
}
Of course this isn't exactly how Where works, but you can get a sense of what happens under the hood re the Func.
I created a sample here with some diagnostics messages to help you understand the flow.
Why I can change the name of the parameter "number" inside the Where but can't change the name of "index"?
You can change it without breaking things. Here I've changed them to "bob" and "simon" and it still works.
Why does this code produces the output 0, 20, 15, 40? I know the indexes are from 0 to 7.
Your checks are performed like this:
Index | Check
0 | 0 <= 0 (because 0 * 10 == 0) result = true
1 | 30 <= 10 (because 1 * 10 == 10) result = false
2 | 20 <= 20 (because 2 * 10 == 20) result = true
3 | 15 <= 30 (because 3 * 10 == 30) result = true
4 | 90 <= 40 (because 4 * 10 == 40) result = false
5 | 85 <= 50 (because 5 * 10 == 50) result = false
6 | 40 <= 60 (because 6 * 10 == 60) result = true
7 | 75 <= 70 (because 7 * 10 == 70) result = false
What is the usage of the left arrow in "number <= index * 10" and what is the official name of this left arrow? (I know the right arrow is to separe input and output in a lambda expression)
The left arrow is the mathematical symbol for "less than". Combined with the equals, it is "less than or equal to". See comparison operators for more.
Related
Prime Number Generator Code
Do know that this question should be quite basic but i have spent hours trying to figure out why my code is stuck in the loop as below. Have added a Console.WriteLine($"{counttemp} , {count1} "); in the if loop to check the 2 numbers and seems like it is not breaking out of the if condition when the condition is true
this is the console output for the writeline in the if loop
5 , 5
6 , 2
7 , 7
8 , 2
9 , 3
10 , 2
11 , 11
12 , 2
13 , 13
14 , 2
15 , 3
16 , 2
17 , 17
18 , 2
19 , 19
Problematic Loop??
for (count1 = 2; count1 <= counttemp ; ++count1)
{
if(counttemp % count1 == 0)
{
Console.WriteLine($"{counttemp} , {count1} ");
Console.ReadKey();
primetest1 = 0;
break;
}
}
full code sequence
static void Main(string[] args)
{
int prime1 = 10000, count1, primetest1, counttemp;
for (counttemp = 5; counttemp <= prime1; counttemp++)
{
primetest1 = 1;
for (count1 = 2; count1 <= counttemp ; ++count1)
{
if(counttemp % count1 == 0)
{
Console.WriteLine($"{counttemp} , {count1} ");
Console.ReadKey();
primetest1 = 0;
break;
}
}
if (primetest1 == 1)
{
Console.Write($"{counttemp}");
}
}
}
You're almost there. The problem is that you're checking if your candidate number is a prime by getting the remainder when divided by each number up to and including the number itself.
I think you'll find that N is a factor of N for all values of N. To fix this, you should only be checking up to but excluding the number.
And, as an aside, you don't really need to check all the way up to N - 1. You only need to go to the square root of N, adjusted up to the nearest integer. That's because, if it has a factor above the square root, you would already have found a factor below it.
Consider 24 as an example. It has 6, 8, and 12 as factors above the square root, but the matching values below the square root are 4, 3, and 2 respectively.
And there's a another trick you can use by realising that if a number is a multiple of a non-prime, it's also a multiple of every prime factor of that non-prime. In other words, every multiple of 12 is also a multiple of 2 and 3.
So you only need to check prime numbers up to the square root, to see if there's a factor. And prime numbers, other than two or three, are guaranteed to be of the form 6x-1 or 6x+1, so it's quite easy to filter out a large chunk of candidates very quickly, by checking only for those values.
In other words, check two and three as special cases. Then start at 5 and alternately add 2 and 4: 5, 7, 11, 13, 17, 19, .... Not every number in that set is prime (e.g, 25) every prime is guaranteed to be in that set.
You can check out an earlier answer of mine for more detail on why this is so, and how to do this sequence efficiently.
Okay so I'm new to coding and I just started an account here to get some help.
My assignement is to code an application that will print numbers from 0-100 in the console. But not "32, 44 and 77".
I know I could make many If statement, but my question is if I can store the three numbers in an Array and then say like:
int numZero = 0;
int[] num = { 32, 44, 77 };
while (numZero <= 100)
{
Console.WriteLine(numZero);
numZero++;
// I know the num needs to have a value assigned. But can I make the "numZero" go through the three numbers in num?
if (numZero == num [])
{
numZero++;
}
thankful for advice!
You can use a for loop from 0 to 100 and in the loop you test if the index Exists() in the array to not print else to print.
You can also use the Linq extension method Contains() instead of Array.Exists().
Doing that you will have 3 lines of code:
for
if !contains
print (you do nothing if contains).
Thus you can try this:
using System.Linq;
int[] num = { 32, 44, 77 };
for ( int index = 0; index <= 100; index++ )
if ( !num.Contains(index) )
Console.WriteLine(index);
You can aslo write:
foreach ( int index in Enumerable.Range(0, 101) )
if ( !num.Contains(index) )
Console.WriteLine(index);
Using Enumerable.Range avoids manipulating index and increment, so the code is cleaner and more secure.
Note: if 100 is not included change <= to <, or use Range(0, 100).
I am looking to create a program like the following (c# btw):
int[] arr = new int[9]
//some code that puts values 1, 0, or 2 in each array element
for(int i = 0; i < arr.Length; i++)
{
if (arr[i] == arr[i + 3]) { return true; }
}
So, for each value in the array I am applying a formula that does something with that value and the value 3 indexes ahead of it. Of course, this runs into an out of range exception once i+3>8.
What I'd like to do is if the the desired index is out of range then loop the index values back around to the beginning of the array. So, in an array of length 9 where the last index is 8, if on a given loop i = 7, and i+3 then = 10, I would like i+3 to 'become,' by whatever means, 1, and then when i = 8, and i+3 = 11, I want i+3 to become 2.
So, the index pairs being evaluated would be something like:
i , i+3
0 3
1 4
2 5
3 6
4 7
5 8
6 0
7 1
8 2
how can I go about doing this?
Thanks for any help.
Use the modulo operator like this:
if (arr[i] == arr[(i + 3) % arr.Length]) { return true; }
You could try the following expression inside your if statement.
arr[i] == arr[(i + 3) % arr.Length];
The % Operator
Divides the value of one expression by the value of another, and
returns the remainder.
I'm making a game in unity, and I have this 'if statement' that by every 5 waves my shop menu will become visible. The code does work, but I am certain I'm doing something wrong or could do something better!
if (waveCount == 5 || waveCount == 10 || waveCount == 15 || waveCount == 20 || waveCount == 25 || waveCount == 30 || waveCount == 35 || waveCount == 40 || waveCount == 45 || waveCount == 50)
{
// yield return new WaitForSeconds(shopWait);
shopPanel.SetActive(true);
}
As you can see the 'if statement' not that good, normally it continues all the way to waveCount == 100 but i cut that out. There must be a simpler or cleaner way to do this :/ but i just can't wrap my head around it :(
Edit 1:
Thanks, I didn't know much about modulo, know I know what I have to read about :)
You can use modulo operation:
if (waveCount % 5 == 0)
Yes, there are indeed simpler ways of doing this. If you use a little bit of maths and logic, you can figure this out.
Since you want to check whether the value of waveCount is a multiple of 5, you can use % to get the reminder of waveCount / 5. If that reminder is 0, waveCount is a multiple of 5.
if (waveCount % 5 == 0 && waveCount <= 100)
I added waveCount <= 100 to replicate your code's behaviour when waveCount is larger than 100 i.e. not get into the if statement.
Alternatively, you can put all the values into a list:
var list = new List<int>();
for (int i = 1 ; i <= 20 ; i++) {
list.Add(i * 5);
}
And then check whether the list contains the number:
if (list.Contains(waveNumber))
The advantage of this is that if you decided to change how the game works and say that the shop menu can be opened at waves 9, 52, and 77, you just add the numbers to the list, without modifying the if statement. This provides a lot of flexibility.
if (waveCount % 5 == 0 && waveCount <= 50) {
//...code
}
If your “if” statement's body just contains shopPanel.SetActive(true); you can do that without even using “if” like that.
shopPanel.SetActive(waveCount % 5 == 0 && waveCount <= 50);
Give it a try
if (waveCount % 5 == 0 && waveCount <= 50)
Use the modulo-operator:
if(waveCount % 5 == 0 && waveCount <= 100) ...
The operator calculates the remainder of an integer-divison. In your case the statement should return zero indicating that your number divided by 5 has no remainder.
Just to generalize: in case the data you have doesn't match a pattern, you can put all the things to match against in a set, then test the set for membership:
var thingsToMatch = Set(2, 5, 8, 14, 23, 80, 274...);
if (someNumber in thingsToMatch) {...}
As long as you know the set isn't being recreated everytime the function is called, this has proven to be fairly fast. If your language doesn't automatically cache the set, you can make it a static variable of the function.
You can use the remainder operator for this:
if (waveCount % 5 == 0 && waveCount > 0 && waveCount <= 50)
{
//yield return new WaitForSeconds(shopWait);
shopPanel.SetActive(true);
}
You can test whether the remainder of the division by 5 is 0, which means that the number is divisible by 5.
if (waveCount % 5 == 0 && waveCount >= 5 && waveCount <= 50)
C# performs integer math on integer number types (int, long, uint, ...).
Example:
13 / 5 = 2
I.e. you never get a decimal fraction part. The complementary operation is the modulo operation. It gives you the remainder of this division:
13 % 5 = 3
I.e., 13 / 5 is 2 plus remainder 3. Together, division and modulo operation allow you to perform the reverse operation.
(5 * (13 / 5)) + (13 % 5) =
(5 * 2 ) + ( 3 ) = 13
If you have irregular figures, quite different approaches are to use a switch statement:
switch (waveCount) {
case 5:
case 10:
case 15:
case 20:
case 25:
case 30:
case 35:
case 40:
case 45:
case 50:
shopPanel.SetActive(true);
break;
}
or an array of allowed values:
private static readonly int[] AllowedValues =
new int[] { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 };
if(Array.IndexOf(AllowedValues, waveCount) >= 0) { ... }
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Given the value I want a number of items to total, how can I programmatically determine how many need to be of an alternate/adjusted value to equal (as close as possible, anyway) the given value?
More specifically, say I had 290 items that needed to total 2700. The default value is 10, but if the given value is less than (item count * 10) - which would be 2900 in this case, a certain number of those items will have to have a value of 9 instead of 10; OTOH, if the given value is greater than (item count * 10), a certain number of those items will have to have a value of 11 instead of 10 (for example, if the given value was still 2700, but the item count was 250). Eight and twelve would never be used - only 9, 10, and 11.
In these cases, there would be 200 nines and 90 tens in the first case:
200 * 9 == 1800
90 * 10 == 900
2700
...and 200 elevens and 50 tens in the second case:
200 * 11 == 2200
50 * 10 == 500
2700
I need a function that will take the given value, and the item count, and return the number of "outliers" (9s or 11s). IOW, the function would look like this:
function int GetOutlierCount(int ValToEqual, int ItemCount) {
// TODO: How?
}
...and be called like this:
GetOutlierCount(2700, 290)
-or:
GetOutlierCount(2700, 250)
...etc. In both cases shown above, it would return 200, as 200 9s are needed in the first case, and 200 11s in the second case (the caller would know which to expect, based on whether ValToEqual was 10* greater than (ItemCount * 10) or not.
OK, you have n integers each of value v.
You have a total t that you want to achieve, where n * (v-1) <= t <= n * (v+1).
If t < n * v, you have to decrease (n*v) - t of your integers by 1 to total t.
If t > n * v, you have to increase t - (n*v) of your integers by 1 to total t.
Your first example has n = 290, v = 10, t = 2700. 2700 < 290 * 10 holds so you need to adjust (290*10) - 2700 = 200 of your items downwards.
Your second example has n = 250, v = 10, t = 2700. 2700 > 250 * 10 holds so you need to adhust 2700 - (250*10) = 200 of your items upwards.
(In case I've not made it obvious enough: the number of items you need to change is simply the difference between your desired total and your actual total.)
Brute force implementation. Linear time, so still pretty good. Left here for posterity, since I first mistakenly thought this was a hard problem. :)
def outlier_count(target_val, count):
default_val = 10
other_val = default_val - 1
x_max = target_val / default_val
for x in range(x_max, -1, -1): # x_max, x_max-1, ..., 0
y = count - x
if x*default_val + y*other_val == target_val:
return (x, y)
raise ValueError("No solution")
function int GetOutliers(int totalVal, int itemsCount) {
const int DEFAULT_MULTIPLIER = 10;
int icMultiplied = itemsCount * DEFAULT_MULTIPLIER;
return Math.Abs(totalVal - icMultiplied);
}