results.Where(x=>x.Members.Any(y=>members.Contains(y.Name.ToLower())
I happened to see this query in internet. Can anyone explain this query please.
suggest me a good LINQ tutorial for this newbie.
thank you all.
Edited:
what is this x and y stands for?
x is a single result, of the type of the elements in the results sequence.
y is a single member, of the type of the elements in the x.Members sequence.
These are lambda expressions (x => x.whatever) that were introduced into the language with C# 3, where x is the input, and the right side (x.whatever) is the output (in this particular usage scenario).
An easier example
var list = new List<int> { 1, 2, 3 };
var oddNumbers = list.Where(i => i % 2 != 0);
Here, i is a single int item that is an input into the expression. i % 2 != 0 is a boolean expression evaluating whether the input is even or odd. The entire expression (i => i % 2 != 0) is a predicate, a Func<int, bool>, where the input is an integer and the output is a boolean. Follow? As you iterate over the query oddNumbers, each element in the list sequence is evaluated against the predicate. Those that pass then become part of your output.
foreach (var item in oddNumbers)
Console.WriteLine(item);
// writes 1, 3
Its a lambda expression. Here is a great LINQ tutorial
Interesting query, but I don't like it.
I'll answer your second question first. x and y are parameters to the lambda methods that are defined in the calls to Where() and Any(). You could easy change the names to be more meaningful:
results.Where(result =>
result.Members.Any(member => members.Contains(member.Name.ToLower());
And to answer your first question, this query will return each item in results where the Members collection has at least one item that is also contained in the Members collection as a lower case string.
The logic there doesn't make a whole lot of sense to me with knowing what the Members collection is or what it holds.
x will be every instance of the results collection. The query uses lambda syntax, so x=>x.somemember means "invoke somemember on each x passed in. Where is an extension method for IEnumerables that expects a function that will take an argument and return a boolean. Lambda syntax creates delegates under the covers, but is far more expressive for carrying out certain types of operation (and saves a lot of typing).
Without knowing the type of objects held in the results collection (results will be something that implements IEnumerable), it is hard to know exactly what the code above will do. But an educated guess is that it will check all the members of all the x's in the above collection, and return you an IEnumerable of only those that have members with all lower-case names.
Related
In my C# winforms project, I wanted to update a specific index based position in a collection (named List l1 here).
I tried below code:
l1.Where((s, i1) => i1 == intvalue).Select(s => { if (s > 0) s = -1; return s; };
I wanted to set value at invalue index to -1 in the list l1, but when I do so with above statement the value in l1 is not changed. Please help! I am new to Linq and have searched the topic 'index based change of value in a collection' everywhere, but can't resolve my problem as it involves BigInteger type and I have so many elements in the list that their total count passes the allowed max value for int type in c#. So when I type l1[intvalue] it says can't convert BigInteger to int for index position.
Thanks
LINQ is Language INtegrated Queries. It's purpose is querying data. If you want to modify list item:
if (l1[intvalue] > 0)
l1[intvalue] = -1;
Also I'd like to explain why your query is not changing list.
On first step you are selecting list items by some condition. Very strange condition by the way. If you want to select item by index, there is operator ElementAt.
Then you are doing projection. I.e. you are calling anonymous method which accepts each selected item and produce some result. Each item passed to that method as s argument. And when you are assigning -1 to s you are actually assigning value to method argument. That does not affect items in the list. Even if your list will contain items of reference type instead of integers, assigning value to method argument will just change where argument variable points. It will not change references in original list. Though you still can modify items of reference type. But such side-effects in projection methods are not good practice.
What is the difference between LINQ and Lambda Expressions? Are there any advantages to using lambda instead of linq queries?
Linq is language integrated query. When using linq, a small anonymous function is often used as a parameter. That small anonymous function is a lambda expression.
var q = someList.Where(a => a > 7);
In the above query a => a > 7 is a lambda expression. It's the equivalent of writing a small utility method and passing that to Where:
bool smallMethod(int value)
{
return value > 7;
}
// Inside another function:
var q = someList.Where(smallMethod);
This means that your question is really not possible to answer. Linq and lambdas are not interchangeable, rather lambdas are one of the technologies used to implement linq.
LINQ is Language integrated query, where is lamda expression are similar to Annonymous method for .Net 2.0.
You can't really compare them may be you are confused because LINQ is associated with lamda expression most of the time.
You need to see this article: Basics of LINQ & Lamda Expressions
EDIT: (I am not so sure, but may be you are looking for the difference between Query Syntax and Method Sytnax)
int[] numbers = { 5, 10, 8, 3, 6, 12};
//Query syntax:
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
//Method syntax:
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
In the above example taken from MSDN, Method Sytnax contains a lamda expression (num => num % 2 == 0) which works like a method, takes number as input and returns true if they are even.
They both are similar, and in the words of Jon Skeet, they both compile to similar code.
In a nutshell:
LINQ is a quering technology (Language Integrated Query). LINQ makes extensive use of lambda's as arguments to standard query operator methods such as the Where clause.
A lambda expression is an anonymous function that contain expressions and statements. It is completely separate and distinct from LINQ.
See the two Linq (to SharePoint) code samples below.
The only differences are the highlighted sections of code. The first statement works as expected with a hard-coded where clause, but the 2nd set of code throws the error “Value does not fall in within the expected range” when I try to do a count on the items. What am I missing?
Works
relatedListItems = dc.GetList<GeneralPage>("Pages")
.Where(x => x.RelatedPracticesTitle.Any(y=>y=="Foo"))
if (relatedListItems.Count() == 0)
{…}
Fails - “Value does not fall within the expected range”
Func<GeneralPage, bool> f = x => x.RelatedPracticesTitle.Any(y => y == "Foo");
relatedListItems = dc.GetList<GeneralPage>("Pages")
.Where(f)
if (relatedListItems.Count() == 0)
{…}
If it's LINQ to Sharepoint, presumably that means it should be using expression trees, not delegates. Try:
Expression<Func<GeneralPage, bool>> f =
x => x.RelatedPracticesTitle.Any(y => y == "Foo");
relatedListItems = dc.GetList<GeneralPage>("Pages").Where(f);
By the way, it's generally a better idea to use Any() rather than Count() if you just want to find out if there are any results - that way it can return as soon as it's found the first one. (It also expresses what you're interested in more clearly, IMO.)
In the first case, you're using the Expression<Func<GeneralPage, bool>> overload and pass an expression which I assume LINQ to SharePoint will try to convert to CAML and execute.
In the second case, you're passing the plain Func<GeneralPage, bool> so LINQ to SharePoint can't figure out how to compose a query (it only sees the delegate, not the expression).
(EDIT: I have asked the wrong question. The real problem I'm having is over at Compose LINQ-to-SQL predicates into a single predicate - but this one got some good answers so I've left it up!)
Given the following search text:
"keyword1 keyword2 keyword3 ... keywordN"
I want to end up with the following SQL:
SELECT [columns] FROM Customer
WHERE
(Customer.Forenames LIKE '%keyword1%' OR Customer.Surname LIKE '%keyword1%')
AND
(Customer.Forenames LIKE '%keyword2%' OR Customer.Surname LIKE '%keyword2%')
AND
(Customer.Forenames LIKE '%keyword3%' OR Customer.Surname LIKE '%keyword3%')
AND
...
AND
(Customer.Forenames LIKE '%keywordN%' OR Customer.Surname LIKE '%keywordN%')
Effectively, we're splitting the search text on spaces, trimming each token, constructing a multi-part OR clause based on each token, and then AND'ing the clauses together.
I'm doing this in Linq-to-SQL, and I have no idea how to dynamically compose a predicate based on an arbitrarily-long list of subpredicates. For a known number of clauses, it's easy to compose the predicates manually:
dataContext.Customers.Where(
(Customer.Forenames.Contains("keyword1") || Customer.Surname.Contains("keyword1")
&&
(Customer.Forenames.Contains("keyword2") || Customer.Surname.Contains("keyword2")
&&
(Customer.Forenames.Contains("keyword3") || Customer.Surname.Contains("keyword3")
);
but I want to handle an arbitrary list of search terms. I got as far as
Func<Customer, bool> predicate = /* predicate */;
foreach(var token in tokens) {
predicate = (customer
=> predicate(customer)
&&
(customer.Forenames.Contains(token) || customer.Surname.Contains(token));
}
That produces a StackOverflowException - presumably because the predicate() on the RHS of the assignment isn't actually evaluated until runtime, at which point it ends up calling itself... or something.
In short, I need a technique that, given two predicates, will return a single predicate composing the two source predicates with a supplied operator, but restricted to the operators explicitly supported by Linq-to-SQL. Any ideas?
I would suggest another technique
you can do:
var query = dataContext.Customers;
and then, inside a cycle do
foreach(string keyword in keywordlist)
{
query = query.Where(Customer.Forenames.Contains(keyword) || Customer.Surname.Contains(keyword));
}
If you want a more succinct and declarative way of writing this, you could also use Aggregate extension method instead of foreach loop and mutable variable:
var query = keywordlist.Aggregate(dataContext.Customers, (q, keyword) =>
q.Where(Customer.Forenames.Contains(keyword) ||
Customer.Surname.Contains(keyword));
This takes dataContext.Customers as the initial state and then updates this state (query) for every keyword in the list using the given aggregation function (which just calls Where as Gnomo suggests.
Imagine a have a very long enunumeration, too big to reasonably convert to a list. Imagine also that I want to remove duplicates from the list. Lastly imagine that I know that only a small subset of the initial enumeration could possibly contain duplicates. The last point makes the problem practical.
Basically I want to filter out the list based on some predicate and only call Distinct() on that subset, but also recombine with the enumeration where the predicate returned false.
Can anyone think of a good idiomatic Linq way of doing this? I suppose the question boils down to the following:
With Linq how can you perform selective processing on a predicated enumeration and recombine the result stream with the rejected cases from the predicate?
You can do it by traversing the list twice, once to apply the predicate and dedup, and a second time to apply the negation of the predicate. Another solution is to write your own variant of the Where extension method that pushes non-matching entries into a buffer on the side:
IEnumerable<T> WhereTee(this IEnumerable<T> input, Predicate<T> pred, List<T> buffer)
{
foreach (T t in input)
{
if (pred(t))
{
yield return t;
}
else
{
buffer.Add(t);
}
}
}
Can you give a little more details on how you would like to recombine the elments.
One way i can think of solving this problem is by using the Zip operator of .Net 4.0 like this.
var initialList = new List<int>();
var resjectedElemnts = initialList.Where( x=> !aPredicate(x) );
var accepetedElements = initialList.Where( x=> aPredicate(x) );
var result = accepetedElements.Zip(resjectedElemnts,(accepted,rejected) => T new {accepted,rejected});
This will create a list of pair of rejected and accepeted elements. But the size of the list will be contrained by the shorter list between the two inputs.