C# Linq questions on select parameters - c#

I have the basic understanding of select method in linq.
var arrayIndex = Enumerable.Range(10, 10).ToArray();
This one will create an array with integers 10 to 19.
For some real life problems, I need to use the index of the original data.
After some research, I found that I can do something like this
var multipliedArray = arrayIndex.Select((i, Index) => i * Index).ToArray();
I know that i is the item itself, in this case i will be integer.
So, just two questions
How do I know the full list of parameters that can put within the bracket (like the Index).
What's the other use case for having different parameter in the bracket.

The part within the Select...
(i, Index) => i * Index
...is lambda expression, which is equivalent to an anonymous method. If you would write the method non-anonymously, it would look like this:
int Calculate(int i, int Index) {
return i * Index;
}
When you want to pass a method as an argument, the respective parameter needs to be a delegate that matches the method's signature. The given Calculate nethod and, since they are sharing the same signature, your lambda expression match the signaturee of the Func<int, int, int> delegate. As it turns out, Enumerable.Select<int, int>offers you an overload with exactly this delegate, so you can use your lambda expression. The other (more widely used) overload accepts a Func<int, int>, which is the version without the index. There are no other overloads, so you can not have other arguments in your lambda expression.

For a better understanding, you can refer to the relevant document Or using Code Completion in development environments.

Related

Roslyn - creating a SeparatedList<T> from a yield'ed IEnumerable<T>

I am trying to build a SeparatedList using a dynamically-generated IEnumerable sequence (which is constructed by an Enumerable.Select() function call). The API function to create a SeparatedList takes two parameters, an IEnumerable<T> and an IEnumerable<SyntaxToken>. I have provided a simple function, Repeat, that is an infinite sequence generator which yields as many commas, in this case, as are requested.
The SeparatedList function appears to consume as many of the first sequence (parameter types here) as there are entries in the second sequence, which messes me up. Have I misunderstood how the function is supposed to work and has anyone else done this? Thanks
Syntax.SeparatedList<ParameterSyntax>(
functionParameterTypes,Repeat(i=>Syntax.Token(SyntaxKind.CommaToken)))
(Edit: I should add that converting the functionParameterTypes to a List<> and passing another List<> with one fewer token than elements in functionParameterTypes does work but I am trying to do this without having to explicitly build the list ahead of time.)
The XML documentation for the separators parameter says:
The number of tokens must be one less than the number of nodes.
You're right that this is not what the method actually requires: The number of tokens must be one less than the number of nodes or same as the number of tokens. I wouldn't be surprised if this was intentional, code like f(foo, bar, ) makes sense if you're trying to handle code that's just being written.
I think that calling ToList() on the sequence of parameters is the best choice here. And you don't have to use another List for separators, you can use Enumerable.Repeat() for that. For example like this (taken from a library I wrote where I faced the same issue):
public static SeparatedSyntaxList<T> ToSeparatedList<T>(
this IEnumerable<T> nodes, SyntaxKind separator = SyntaxKind.CommaToken)
where T : SyntaxNode
{
var nodesList = nodes == null ? new List<T>() : nodes.ToList();
return Syntax.SeparatedList(
nodesList,
Enumerable.Repeat(
Syntax.Token(separator), Math.Max(nodesList .Count - 1, 0)));
}
I also had the same need to create a SeparatedList using a dynamically generated list of parameters. My solution was to use SelectMany() and Take() to add separators (i.e. "comma") to the parameters but then remove the last trailing comma.
SyntaxFactory.SeparatedList<ParameterSyntax>(
functionParameterTypes
.SelectMany(param =>
new SyntaxNodeOrToken[]
{
param,
SyntaxFactory.Token(SyntaxKind.CommaToken)
})
.Take(functionParameterTypes.Count() * 2 - 1)
);

C# - list sorting - x and y

I have this code and I understand that it's sorting the list lstDMV. But please help me break it down.
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
What does => mean? And how does it work based on the integer returned from the compare function?
How can I sort my lstDMV if I'm sorting integers instead of dates?
It's called lambda expression.
For the comparison itself, do have a look at the DateTime.Compare method. See its return values:
< 0 --> t1 is earlier than t2
0 --> t1 is the same as t2
> 0 --> t1 is later than t2
The lambda operator => in
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
basically creates a new delegare with a block of code to excecute. The x and y is past along as parameters.
you could sort a list of int by changing the code to
lstDMV.Sort((x, y) => x.CompareTo(y));
It is called lambda operator. From MSDN;
The => token is called the lambda operator. It is used in lambda
expressions to separate the input variables on the left side from the
lambda body on the right side. Lambda expressions are inline
expressions similar to anonymous methods but more flexible; they are
used extensively in LINQ queries that are expressed in method syntax.
For sorting operation, use Sort() method like this;
lstDMV.Sort((int1, int2) => int1.CompareTo(int2));
=> is a lambda expression operator you can think of it as an anonymous function in javascript
in this case
lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
it is creating a function that is being used as the handler for Sort event.
The complier can infer the types of x and y since it knows the defintion of Close delelegate.
First of all, these are Lambda-Expressions.
Now to your question:
=> is an operator that defines the return value.
In your case (x,y) will return the value of DateTime.Compare(x.NotifDate, y.NotifDate).
Now the Sort()- function of your List will somehow sort the List depending on the value of DateTime.Compare(x.NotifDate, y.NotifDate).
Take a look at the MSDN article: http://msdn.microsoft.com/en-us/library/bb397687.aspx
It's very helpful.
(Others have already answered the lambda operator part of your question)
how can i sort my lstDMV if i'm sorting integers instead of dates?
ints.Sort((i1, i2) => i1.CompareTo(i2));

Very simple explanation of a Lambda Expression

I am looking for a very simple - basic - no hardcore programming mumbo jumbo, simply put a generalized overview of a Lambda Expression in layman's terms.
A lambda expression is, simply put, a re-useable expression which takes a number of arguments:
x => x + 1;
The above expression reads "for a given x, return x + 1".
In .NET, this is powerful, because it can be compiled into an anonymous delegate, a nameless function you can declare inline with your code and evaluate to get a value:
int number = 100;
Func<int, int> increment = x => x + 1;
number = increment(number); // Calls the delegate expression above.
However, the real power of a lambda expression is that it can be used to initialize an in-memory representation of the expression itself.
Expression<Func<int, int>> incrementExpression = x => x + 1;
This means that you can give that expression to something like LINQ to SQL and it can understand what the expression means, translating it into a SQL statement that has the same meaning. This is where lambdas are very different from normal methods and delegates, and normally where the confusion begins.
Lambda Expressions are inline functions that have a different syntax to regular functions.
Example Lambda Expression for squaring a number.
x => x * x
A small unnamed inline method. Is that basic enough for you? I'm not sure what you are looking for exactly.
You also said in "layman's" terms - I presume that you have some level of software development experience (so not a complete layman)
In non functional programming languages expressions (that act on variables) perform calculations and they perform those calculations once.
Lambda expressions allow you to define (in an expression) via different syntax code that can work on a list and can conceptually be considered a function.
You could simplify this to say "They let you define functions in expressions".
Does not quite get to the "why". The why is the more interesting, in my opinion. Lambda expression allow for the manipulation of functions and partial functions.

Dynamic Linq: How to specify the StringComparison type?

I'm working on doing some custom filtering and sorting of a dataset, based on a collection of sort fields sent from the client browser, and am using Dynamic Linq to achieve (most of) the desired effect. Where I'm running into a problem is when I try to sort by a column of type String, which contains both traditional strings and numbers stored as strings. It doesn't appear that I can pass in a StringComparison enum value, or specify an IComparer parameter for the Dynamic Linq orderby function.
My sorting code looks like:
myList.AsQueryable().OrderBy("StringColWithNums ASC")
I end up with:
1
10
100
11
12
2
20
instead of:
1
2
10
11
12
20
100
Anyone have any experience doing something similar?
myList.AsQueryable().Sort((r, s) => int.Parse(r).CompareTo(int.Parse(s)));
will take some tweaking if those are objects, just use int.Parse(r.StringColWithNums), or whatever the field is.
Oops, sorry, didn't read all the OP to see it has letters too and you want the dynamic linq, editing
EDIT
I don't know that you're going to be able to do that using Dynamic linq and passing IComparer. You may be able to do it after getting the results (i.e. as I was originally writing the sort, with modifications). Comment if you want to pursue that line.
This is a fundamental problem with attempting to perform numeric comparisons within a string comparison. A couple of ways I would do this:
When loading the list, prefix numbers with an amount of zeroes that will accompany the max string size, i.e. String.Format("000000", number). This will only work if you care mostly about sorting and less about the appearance of the results - even then, you could convert "000010" back to a numeric and call the ToString() method to display the number again without the leading zeroes.
Write your own implementation (extension method) of OrderBy wherein you pass a function (or anonymous function) as a parameter to re-sort the results calling the method passed in.
You can solve this by writing a new string comparer
class AlphaNumericComparer : IComparer<string>
{
public int Compare(string x, string y)
{
// if both values are integers then do int comparision
int xValue, yValue;
if (int.TryParse(x, out xValue) && int.TryParse(y, out yValue))
return xValue.CompareTo(yValue);
return x.CompareTo(y); // else do string comparison
}
}
Then you can use the comparer in methods like OrderBy and Sort
var sorted = lst.OrderBy(s => s, new AlphaNumericComparer());
lst.Sort(new AlphaNumericComparer());
This will give you the desired result. If not then just tweak the comparer.
It seems that this is not something that can be accomplished out of the box with Dynamic Linq, at least not in .NET 2.0/3.5. I ended up modifying the Dynamic Linq source code in order to accomplish what I needed.

Please explain System.Linq.Enumerable.Where(Func<T, int, bool> predicate)

I can't make any sense of the MSDN documentation for this overload of the Where method that accepts a predicate that has two arguments where the int, supposedly, represents the index of the source element, whatever that means (I thought an enumerable was a sequence and you couldn't see further than the next item, much less do any indexing on it).
Can someone please explain how to use this overload and specifically what that int in the Func is for and how it is used?
The int parameter represents the index of the current item within the current iteration. Each time you call one of the LINQ extension methods, you aren't in theory guaranteed to get the items returned in the same order, but you know they're all be returned once each and thus can be assigned indices. (Well, you are guaranteed if you know the query object is a List<T> or such, but not in general.)
Example:
var result1 = myEnumerable.Where((item, index) => index < 4);
var result2 = myEnumerable.Take(4);
// result1 and result2 are equivalent.
You can't index an IEnumerable<T> in the same way you can an array, but you might be able to use the index to filter the list in some way, or possibly to index some data in another collection which will be used in the condition.
EDIT: As an example, to skip every other element you could use:
var results = sequence.Where((item, idx) => idx % 2 == 0);

Categories