Need to understand the below code using func - c#

I am new to delegates. Today I saw a code on this Link. AS i am new to c# and specially to delegates, i was unable to understand the below code.
public static void Main()
{
Func<String, int, bool> predicate = (str, index) => str.Length == index;
String[] words = { "orange", "apple", "Article", "elephant", "star", "and" };
IEnumerable<String> aWords = words.Where(predicate).Select(str => str);
foreach (String word in aWords)
Console.WriteLine(word);
}
The OutPut of the above code is "star". AS predicate is expecting to parameters but in this case we are not passing any parameters. Your comments will be really appreciated.

So first, there's a function definition:
Func<String, int, bool> predicate = (str, index) => str.Length == index;
which reads as "given a string represented as str and an index represented as index return true if the length of the string is equal to the index otherwise false"
When you come across to the enumerable pipeline:
IEnumerable<String> aWords = words.Where(predicate).Select(str => str);
you pass this function definition above, which is similar to:
words.Where((element, index) => element.Length == index).Select(str => str);
and as you can see only the element "star" meets that criteria, i.e. the "star" has length 4 and its index is also 4.
In regard to your confusion of:
AS predicate is expecting to parameters but in this case we are not
passing any parameters.
Note that when it comes to LINQ, we only specify the "what" and the "how" is an implementation detail. so in the aforementioned code, the Where clause will pass each element and its index to the predicate function.
On another note, the Select is superfluous, just IEnumerable<String> aWords = words.Where(predicate) should shuffice.

Let's start to examine this code from the first line.
Func<String, int, bool> predicate = (str, index) => str.Length == index;
Here we have simply the declaration of a variable named predicate This is a particular kind of variable whose value is a function that receives two parameters of type string and int and it is expected to return a bool. But where is the body of that function? Just after the equals sign. The (str,index) are the parameters and the body is simply a comparison between the length of the parameter str with the value of the parameter index.
=> str.Length == index returns true if the condition matches otherwise returns false
Now that we understand the declaration of the delegate, the next question is where we use it. This is even simpler. We can use it whenever we need a function that matches our delegate.
Now there is an overload of Where IEnumerable extension that expects just that, so we can simply put the predicate variable in that place and call the Where extension

In short, the code just says, "Select all words where the length equals index"
string[] words = { "orange", "apple", "Article", "elephant", "star", "and" };
// select all words where the length equals the index
var aWords = words.Where((str, i) => str.Length == i);
foreach (var word in aWords)
Console.WriteLine(word);
Where<TSource>(IEnumerable<TSource>, Func<TSource,Int32,Boolean>)
Filters a sequence of values based on a predicate. Each element's
index is used in the logic of the predicate function.
Func<T1,T2,TResult> Delegate
Encapsulates a method that has two parameters and returns a value of
the type specified by the TResult parameter.
So the only magic is the Func
Func<String, int, bool> predicate = (str, index) => str.Length == index;
Which (in this case) is just a fancy way of writing
public bool DoSomething(string str, int index)
{
return str.Length == index;
}
In essence its just a delegate, unlike an Action its capable of returning a value
Delegates (C# Programming Guide)
A delegate is a type that represents references to methods with a
particular parameter list and return type. When you instantiate a
delegate, you can associate its instance with any method with a
compatible signature and return type. You can invoke (or call) the
method through the delegate instance.

To simplify it a bit,
var aWords = words.Where(str => str.Length == 4);
is the same as:
Func<string, bool> predicate = str => str.Length == 4;
var aWords = words.Where(predicate);
predicate() executes it, and predicate without () can be used to pass it as parameter to a method.
With local functions (functions that can be declared inside other functions) introduced in C# 7, it can be :
bool predicate(string str) { return str.Length == 4; }
var aWords = words.Where(predicate);

Related

How to find the index of an element in an array inside a lambda expression in c# [duplicate]

This question already has an answer here:
Index in the Select projection
(1 answer)
Closed 3 years ago.
I want to create a function that flips a string's order
example: "hi" => "ih"
here is the code I have come out with so far:
public static string Flip(this string Str)
{
char[] chararray = Str.ToCharArray();
string output = "";
chararray. //i dont know what methoud should be used to execute action
return output;
}
the thing is, i want to know within the lambda expression what is the index of the object that is currently selected ex:x in (x => x ) indexOf is not an option as there can be more then one char from the same type
how can I know the index?
edit:
I don't want to know how to reverse a string, I want to know how to find an index of an object in lambda expression
In the Select and Where extension methods of LINQ, you have an overload that takes two parameters in the lambda, the first is the element, the second is the index.
so in your case if you have a char array:
var reversedArray = charArray
.Select((c, i) => new { Element = c, Index = i })
.OrderByDescending(arg => arg.Index)
.Select(arg => arg.Element)
.ToArray();
This is just to demonstrate how to get the index in LINQ extesions methods.
As the question states this is not about how to reverse a string.

How to find index of a value in array of char?

Suppose I have this array of char:
private char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
.ToCharArray();
I want find the index of the character B, so the code must return 1.
I wrote this method:
public int? GetCharIndex(string code)
{
return _alpha.FirstOrDefault(c => c.ToString() == code.ToUpper());
}
where code is b. The result of GetCharIndex is: 66, why I get this result?
Thanks in advance for any help.
use Array.IndexOf
https://learn.microsoft.com/en-us/dotnet/api/system.array.indexof?view=netframework-4.7.2
The 66 you are getting is 'B' ascii value.
The FirstOrDefault function returns the actual item (B) not the index.
So:
int index = Array.IndexOf(_alpha, code.ToUpper());
As you've mentioned, you'd like to use Linq. The Select in LINQ has an override that let's you expose the index. Getting the first matching value will give us the index of the occurrence. You can also replace the .FirstOrDefault() to .ToList() if you want all indexes on the match.
ToList
char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray();
var code = "b";
var key = _alpha.Select((s, i) => new { i, s })
.Where(t => t.s.ToString().ToUpper() == code.ToUpper())
.Select(t => t.i)
.ToList();
Alternatively the above can also be written as
FirstOrDefault
return _alpha.Select((s, i) => new { i, s }).FirstOrDefault(t => t.s.ToString().ToUpper() == code.ToUpper()).i;
Why I get this result?
Nullable<Char> is implicitly convertible to Nullable<Int32> because Char is implicitly convertible to Int32. That happens in your return statement. You're returning the character from the array if found.
Where people are saying ASCII code, they mean character code; in particular, since .NET uses the UTF-16 character encoding of the Unicode character set the UTF-16 code unit value.
BTW—VB4/5/6/A/Script, Java, JavaScript, … also use UTF-16 for text datatypes.
To use standard LINQ operators, choose one that supplies an index like Select:
Char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
Func<Char, StringComparison, Int32?> GetIndexOf = (code, comparisonType) => {
var value = code.ToString();
return _alpha
.Select((c, i) => c.ToString()
.Equals(value, StringComparison.InvariantCultureIgnoreCase) ? i : (Int32?)null)
.FirstOrDefault(i => i.HasValue); } ;
Debug.Assert(1 == GetIndexOf('B', StringComparison.InvariantCultureIgnoreCase));
Debug.Assert(null == GetIndexOf('3', StringComparison.InvariantCultureIgnoreCase));
And, you do have to decide what you really intend by your ".ToUpper". As a question/code review issue, it's unclear. It would be better to write your question and code (or at least as a code comment) in such a way as it explains what the proper culture is for letter case comparison. You used one that depends on the program's current culture, which is initialized from the user's culture at the time the program started.

Linq error: "string[] does not contain a definition for 'Except'."

Here's my code:
public static string[] SplitKeepSeparators(this string source, char[] keptSeparators, char[] disposableSeparators = null)
{
if (disposableSeparators == null)
{
disposableSeparators = new char[] { };
}
string separatorsString = string.Join("", keptSeparators.Concat(disposableSeparators));
string[] substrings = Regex.Split(source, #"(?<=[" + separatorsString + "])");
return substrings.Except(disposableSeparators); // error here
}
I get the compile time error string[] does not contain a definition for 'Except' and the best extension method overload ... has some invalid arguments.
I have included using System.Linq in the top of the source file.
What is wrong?
Your substrings variable is a string[], but disposableSeparators is a char[] - and Except works on two sequences of the same type.
Either change disposableSeparators to a string[], or use something like:
return substrings.Except(disposableSeparators.Select(x => x.ToString())
.ToArray();
Note the call to ToArray() - Except just returns an IEnumerable<T>, whereas your method is declared to return a string[].
Your problem is that you are using .Except<T>(this IEnumerable<T> source, IEnumerable<T> other) with two different types for T (string and char). Change your delimiters to a string array if you want to use Except.
https://msdn.microsoft.com/en-us/library/vstudio/bb300779%28v=vs.100%29.aspx

Explain Linq Microsoft Select - Indexed [Example]

I'm running throuth Microsoft's 101 LINQ Samples, and I'm stumped on how this query knows how to assign the correct int value to the correct int field:
public void Linq12()
{
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var numsInPlace = numbers.Select((num, index) => new { Num = num, InPlace = (num == index) });
Console.WriteLine("Number: In-place?");
foreach (var n in numsInPlace)
{
Console.WriteLine("{0}: {1}", n.Num, n.InPlace);
}
}
I saw in SO #336758 that there have been errors in the examples before, but it is much more likely that I am just missing something.
Could someone explain this and how the compiler knows how to interpret this data correctly?
EDIT:
OK, I think my confusion comes from the LINQ extension that enables the Select feature to work. The Func and two int parameters IEnumerable<TResult> IEnumerable<int>.Select(Func<int,int,TResult> selector) are most likely the key to my lack of understanding.
I'm not really sure what you are asking of but the Select iterates over the list starting at index 0. If the value of the element at the current index is equal to the index it will set the InPlace property in the anonymous object to true. My guess is that the code above prints true for 3, 6 and 7, right?
It would also make it easier to explain if you write what you don't understand.
Jon Skeet has written a series of blog post where he implement linq, read about Select here: Reimplementation of Select
UPDATE: I noticed in one of your comment to one of the other comments and it seems like it is the lambda and not linq itself that is confusing you. If you read Skeet's blog post you see that Select has two overloads:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, int, TResult> selector)
The Select with index matches the second overload. As you can see it is an extension of IEnumerable<TSource> which in your case is the list of ints and therefor you are calling the Select on an IEnumerable<int> and the signature of Select becomes: Select<int, TResult>(this IEnumerable<int> source, Func<int, int, TResult> selector). As you can see I changed TSource against int, since that is the generic type of your IEnumerable<int>. I still have TResult since you are using anonymous type. So that might explain some parts?
Looks correct to me.
First you have an anonymous type with Num and InPlace being created. Then the LINQ Select is just iterating over the elements with the element and the index of that element. If you were to rewrite it without linq and anonymous classes, it would look like this:
class NumsInPlace
{
public int Num { get; set; }
public bool InPlace { get; set; }
}
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
List<NumsInPlace> numsInPlace = new List<int>();
for (int index = 0; i < numbers.length; i++)
{
int num = numers[index];
numsInPlace.Add(new NumsInPlace() { Num = num, InPlace = (index == num) });
}
Console.WriteLine("Number: In-place?");
foreach (var n in numsInPlace)
{
Console.WriteLine("{0}: {1}", n.Num, n.InPlace);
}
The MSDN on Enumerable.Select has the details, but the projection function (num, index) always has the item first, then the index second (if supplied).
how does the compiler know that LINQ Select is using the index value as an index to the array?
The compiler doesn't know about index values. The implementation of that overload of Select knows about index values.
//all the compiler sees is a method that accepts 2 int parameters and returns a bool.
Func<int, int, bool> twoIntFunc = (x, y) => (x == y);
//The compiler sees there's an overload of Enumerable.Select which accepts such a method.
IEnumerable<bool> query = numbers.Select(twoIntFunc);
Enumerable.Select's implementation does the rest of the work by calling that method with the appropriate parameters.
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.
So - Select will call your method with (5, 0) first, then Select calls it with (4, 1).
The lambda expression (num, index) => new { Num = num, InPlace = (num == index) } is executed once for each element in the input sequence and passed the item and it's index as the arguments.
Update
Lambda expressions can be implicitly typed, that is, from the required type, the compiler can figure out (or imply) what types you intend the arguments to be.
(num, index) => new { Num = num, InPlace = (num == index) }
is equivalent to
someAnonymousType MyMethod(int num, int index)
{
return new
{
Num = num,
InPlace = (num == index)
};
}
obviously you can't write the latter because you can't type the name of an anonymous type, but the compiler can ;)
The compiler knows this because the overload of Select that you're using accepts a Func<TSource, Int32, TResult>, this is a Func that takes, two arguments of type TSource (the type of your IEnumberable<T>, in this case int) and an Int32 (which represents the index) and returns an object of TResult, being whatever you choose to return from your function, in this case, an anonymous type.
The lambda can be cast to the required type and therefore it just works.
The second argument in the select is the index, which increments as the compiler traverses the array of numbers. The compiler will see
num index num = index
5 0 false
4 1 false
1 2 false
3 3 true
9 4 false
8 5 false
6 6 true
7 7 true
2 8 false
0 9 false
It provides true for 3,6 and 7. You need to remember it starts with the index at 0.

Explanation of Func

I was wondering if someone could explain what Func<int, string> is and how it is used with some clear examples.
Are you familiar with delegates in general? I have a page about delegates and events which may help if not, although it's more geared towards explaining the differences between the two.
Func<T, TResult> is just a generic delegate - work out what it means in any particular situation by replacing the type parameters (T and TResult) with the corresponding type arguments (int and string) in the declaration. I've also renamed it to avoid confusion:
string ExpandedFunc(int x)
In other words, Func<int, string> is a delegate which represents a function taking an int argument and returning a string.
Func<T, TResult> is often used in LINQ, both for projections and predicates (in the latter case, TResult is always bool). For example, you could use a Func<int, string> to project a sequence of integers into a sequence of strings. Lambda expressions are usually used in LINQ to create the relevant delegates:
Func<int, string> projection = x => "Value=" + x;
int[] values = { 3, 7, 10 };
var strings = values.Select(projection);
foreach (string s in strings)
{
Console.WriteLine(s);
}
Result:
Value=3
Value=7
Value=10
A Func<int, string> eats ints and returns strings. So, what eats ints and returns strings? How about this ...
public string IntAsString( int i )
{
return i.ToString();
}
There, I just made up a function that eats ints and returns strings. How would I use it?
var lst = new List<int>() { 1, 2, 3, 4, 5 };
string str = String.Empty;
foreach( int i in lst )
{
str += IntAsString(i);
}
// str will be "12345"
Not very sexy, I know, but that's the simple idea that a lot of tricks are based upon. Now, let's use a Func instead.
Func<int, string> fnc = IntAsString;
foreach (int i in lst)
{
str += fnc(i);
}
// str will be "1234512345" assuming we have same str as before
Instead of calling IntAsString on each member, I created a reference to it called fnc (these references to methods are called delegates) and used that instead. (Remember fnc eats ints and returns strings).
This example is not very sexy, but a ton of the clever stuff you will see is based on the simple idea of functions, delegates and extension methods.
One of the best primers on this stuff I've seen is here. He's got a lot more real examples. :)
It is a delegate that takes one int as a parameter and returns a value of type string.
Here is an example of its usage:
using System;
class Program
{
static void Main()
{
Func<Int32, String> func = bar;
// now I have a delegate which
// I can invoke or pass to other
// methods.
func(1);
}
static String bar(Int32 value)
{
return value.ToString();
}
}
Func<int, string> accepts an int value parameter and returns a string value. Here's an example where an additional supporting method is unnecessary.
Func<int, string> GetDogMessage = dogAge =>
{
if (dogAge < 3) return "You have a puppy!";
if (dogAge < 7) return "Strong adult dog!";
return "Age is catching up with the dog!";
};
string youngDogMessage = GetDogMessage(2);
NOTE: The last object type in Func (i.e. "string" in this example) is the functions return type (i.e. not limited to primitives, but any object). Therefore, Func<int, bool, float> accepts int and bool value parameters, and returns a float value.
Func<int, bool, float> WorthlessFunc = (intValue, boolValue) =>
{
if(intValue > 100 && boolValue) return 100;
return 1;
};
float willReturn1 = WorthlessFunc(21, false);
float willReturn100 = WorthlessFunc(1000, true);
HTH

Categories

Resources