lambda expression for Enumerable.Select - c#

I'm trying to figure out how to start using linq and lambda expressions.
First of all, if someone could direct me to some good tutorials it will be most appreciated.
Secondly:
I'm trying to select all values which are equal to a specific value using Select method.
I have noticed that select could be defined with a
Select<TSource,TResult>(...lambda expression...)
Now for this purpose I want to select all the numbers which are equal to 5.
int[] numbers = { 1, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
IEnumerable<int> res = numbers.Select( x=>5 );
This does not work, I just don't understand how this works.
And in what situation should I define TSource and TResult, and what would they be in this case?
Thanks in advance!

Select() is used to project each member of the old sequence into a new member of a new sequence. To filter, you use Where():
var evens = numbers.Where(x => x % 2 == 0);
var theFiveSequence = numbers.Where(x => x == 5);
An example of using Select() might be multiplying each number by two:
var doubledNumbers = numbers.Select(x => 2*x);
You can combine those methods together, too:
var doubledNumbersLessThanTen = numbers.Select(x => 2*x).Where(x < 10);
Two important things to remember about LINQ:
The elements of the base sequence are (almost always) not modified. You create new sequences from old sequences.
The queries you write are lazily evaluated. You won't get results from them until you use them in a foreach loop, or call .ToList(), .ToArray() etc.

Related

C#: Gets unmatched elements between 2 collections with Linq & Lambda

I have two collections, compare them and want to get the unmatched items and put into a new collection. I don't want to use conventional method using 2 foreach loop. How to implement it using linq and lambda expression?
e.g.
int[] collection1 = new int[] { 1, 2, 3, 4, 5 };
int[] collection2 = new int[] { 2, 3 };
// Goal: Using Linq and Lambda Expression: the new collection3 should contain 1, 4, 5
Edited: sorry I forget to mention: collection2 is a subset of collection1, therefore all elements in collection2 must exist in collection1.
Something like this?
int[] collection3 = collection1.Except(collection2).ToArray();
int[] collection3 = collection1.Union(collection2).Except(collection1.Intersect(collection2)).ToArray();
var result = collection1.Except(collection2).Concat(collection2.Except(collection1)).ToArray();
You can use Enumerable.Except Method:
var result = collection1.Except(collection2);
As mentioned in the comments, if also the unique elements from the second collection should be added, your code would look like:
var result = collection1.Except(collection2).Concat(collection2.Except(collection1));

C# Linq to Objects/Syntax and Effectively searching if a collection members exist in another collection of sub-collections

I have the first collection of numbers: (1,3,5,6,23)
and the second collection of collections of 1 to n integers
(3), (6,1), (1,3,5,23,6,14,67), (2,3)
So the second collection has elements a, b, c and d which themselves are a collection of integers
a=(3), b=(6,1), c=(1,3,5,23,6,14,67), d=(2,3)
So this can be basically a jagged array)
How to do Linq to object queries using both extension method syntax, and query expression syntax
to find out what combination of numbers in the first collection can be found in collection of a, b, c or d or nowhere. In other words which numbers from the second collection are contained in the first collection.
Q1: I would like to see a=(3), b=(6,1) being found since the members of each collection a and b c exist in the first collection.
Q2: I would like to see the opposite case where we start from the second collection and try to find if its sub collection members belong to the first collection.
I would like to know pros and cons of both approaches. In actuality I will deal with thousands of collections with up to 10 numbers in each.
Something like this?
int[] firstSet = new[] { 1,3,5,6,23 };
int[][] secondSet = new[]
{
new [] { 3 },
new [] { 6, 1 },
new [] { 1,3,5,23,6,14,67 },
new [] { 2, 3}
};
// only subsets where each member matces a member of the first set
var matchinSubSets = from subset in secondSet
where subset.All(x => firstSet.Contains(x))
select subset;
As for performance, dont worry about that to much, if you're only gonna match thousands of entries, it will be done calculating before you know it
Here you go. Have a try of these:
var xs = new [] { 1, 3, 5, 6, 23, };
var yss = new []
{
new [] { 3, },
new [] { 6, 1, },
new [] { 1, 3, 5, 23, 6, 14, 67, },
new [] { 2, 3, },
};
I'll answer your second question first:
var q2 =
from ys in yss
where !ys.Except(xs).Any()
select ys;
var q2b = yss.Where(ys => !ys.Except(xs).Any());
These two queries are identical - except one is in LINQ and the other in extension method syntax. The compiler will generate the same code for both.
Question one is a nightmare - much harder to do.
var q1 =
from z in yss.Zip(
xs.Aggregate(
yss.AsEnumerable(),
(_yss, x) => (
from ys in _yss
select ys.Except(new [] { x }).ToArray())),
(ys, _ys) => new { ys, _ys })
where !z._ys.Any()
select z.ys;
var q1b =
yss.Zip(
xs.Aggregate(
yss.AsEnumerable(),
(_yss, x) => _yss
.Select(ys =>
ys.Except(new [] { x }).ToArray())),
(ys, _ys) => new { ys, _ys })
.Where(z => !z._ys.Any())
.Select(z => z.ys);
Again both in LINQ and extension method syntax and both compiled to the same code.
I ran some performance tests and the "q2" queries are over 10x faster to complete than the "q1" queries.
In one test I had xs with 61 distinct elements, yss with 100,000 distinct valued sub-collections with 956,512 elements in total and the "q1" queries ran in 5,354.1 milliseconds & "q2" ran in 302.1 milliseconds - 17.7x factor.
However, drop this to xs of 10 & yss with 10,000 & 95,641 then the results were 115.3 & 7.4 milliseconds respectively. Either approach would probably be fast enough.

Using linq to determine if any element is ListA exists in ListB?

I'm trying to use PredicateBuilder to compose dynamic linq queries. In my object, I have a list of "Statuses" and I have another list of statuses that I want to search for.
So I need to be able to look in my object.Status property (a list) and see if it contains any of the items in my query list.
I've been fiddling around with .Any() and .Contains() but can't seem to find the right syntax.
What am I doing wrong? Below are some of the things I've tried, but none of them have the correct syntax.
myObject.Statuses.Contains(myStatusList);
myObject.Statuses.Any(myStatusList);
myObject.Statuses.Any(s => s == myStatusList);
got.Any(x => want.Contains(x))
On further reflection, however, I'd write a ContainsAny extension method, to make this more readable. The implementation would probably be the same (although want.Intersect(got).Any() would also work).
Do you mean:
myObject.Statuses.Any(s => myStatusList.Contains(s));
? This would be equivalent too:
myStatusList.Any(s => myObject.Statuses.Contains(s));
What about intersect http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1
public void Linq50()
{
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
var commonNumbers = numbersA.Intersect(numbersB);
Console.WriteLine("Common numbers shared by both arrays:");
foreach (var n in commonNumbers)
{
Console.WriteLine(n);
}
}

Linq TakeWhile depending on sum (or aggregate) of elements

I have a list of elements and want to takeWhile the sum (or any aggregation of the elements) satisfy a certain condition. The following code does the job, but i am pretty sure this is not an unusual problem for which a proper pattern should exist.
var list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
int tmp = 0;
var listWithSum = from x in list
let sum = tmp+=x
select new {x, sum};
int MAX = 10;
var result = from x in listWithSum
where x.sum < MAX
select x.x;
Does somebody know how to solve the task in nicer way, probably combining TakeWhile and Aggregate into one query?
Thx
It seems to me that you want something like the Scan method from Reactive Extensions (the System.Interactive part) - it's like Aggregate, but yields a sequence instead of a single result. You could then do:
var listWithSum = list.Scan(new { Value = 0, Sum = 0 },
(current, next) => new { Value = next,
Sum = current.Sum + next });
var result = listWithSum.TakeWhile(x => x.Sum < MaxTotal)
.Select(x => x.Value);
(MoreLINQ has a similar operator, btw - but currently it doesn't support the idea of the accumulator and input sequence not being the same type.)

LINQ Keyword search with orderby relevance based on count (LINQ to SQL)

This is what i have now as a very basic search:
var Results = from p in dx.Listings select p;
if (CategoryId > 0) Results = Results.Where(p => p.CategoryId == CategoryId);
if (SuburbId > 0) Results = Results.Where(p => p.SuburbId == SuburbId);
var OrderedResults = Results.OrderByDescending(p => p.ListingType);
OrderedResults = OrderedResults.ThenByDescending(p => p.Created);
I understand that i can add in a .Contains() or similar and put in keywords from a keyword box (split into individual items) and that should get the list of results.
However i need to order the results by basic relevance. Meaning that if record A contains 2 of the keywords (in the 'Body' nvarchar(MAX) field) it should be higher than record B that only matches against 1 of the keywords. I don't need a full count of every hit... however if thats eaiser to manage that would be fine.
So is there any way to get the hit count directly in as part of the orderby nicely? I can manage it by getting the results and parsing however i really don't want to do that as parsing possibly thousands could chug the IIS machine, while the SQL Server is a decently powerful cluster :)
If anyone has any ideas or tips it would be a big help.
If I understand you correctly you want to call OrderyByDescending( p => p.Body ) but it should be ordered by how many times a certain word appreas in p.Body ?
Then you should be able to create a method that counts the occurrences and returns the count number then you can simply do OrderyByDescending( p => CountOccurences(p.Body) )
You can alternatively create a BodyComparer class that implements IComparer and then pass it to OrderByDescending
EDIT:
take a look a this link Enable Full Text Searching
Here is a simple example, if I understand what you're looking for correctly:
var storedData = new[]{
new int[] {1, 2, 3, 4},
new int[] {1, 2, 3, 4, 5}
};
var itemsFromTextBox = new[] { 3, 4, 5 };
var query = storedData.Where(a => a.ContainsAny(itemsFromTextBox))
.OrderByDescending(a => itemsFromTextBox.Sum(i => a.Contains(i)? 1:0));
With the following ContainsAny extension:
public static bool ContainsAny<T>(this IEnumerable<T> e1, IEnumerable<T> e2)
{
foreach (var item in e2)
{
if (e1.Contains(item)) return true;
}
return false;
}

Categories

Resources