Category: Linq

Sep 25 2015

How can I use Linq and c# to compare a property against a List<string>

I have code that is filtering a List using code like this..

    List<Product> products = new List<Product>() { /*<INIT THE COLLECTION>*/ }
    //get the ones you need.
    var newListOfProducts = products.Where(p=>p.MyProperty == "prop1" || p.MyProperty == "prop2" || p.MyProperty == "prop3");

My preferences is to use syntax like this...

List<string> stringsToCompare = new List<string>() {"prop1","prop2","prop3"};
var newListOfProducts = products.Where(p=>p.MyProperty.IsInList(stringsToCompare));

This way I can dynamically build the stringToCompare instead of hard-coding them.

But I can't figure out how to do it despite googling for the last half-hour. I think Intersect or Union can work but I can't get the syntax right.

Sep 25 2015

How can I use Linq and c# to compare a property against a List<string>

I have code that is filtering a List using code like this..

    List<Product> products = new List<Product>() { /*<INIT THE COLLECTION>*/ }
    //get the ones you need.
    var newListOfProducts = products.Where(p=>p.MyProperty == "prop1" || p.MyProperty == "prop2" || p.MyProperty == "prop3");

My preferences is to use syntax like this...

List<string> stringsToCompare = new List<string>() {"prop1","prop2","prop3"};
var newListOfProducts = products.Where(p=>p.MyProperty.IsInList(stringsToCompare));

This way I can dynamically build the stringToCompare instead of hard-coding them.

But I can't figure out how to do it despite googling for the last half-hour. I think Intersect or Union can work but I can't get the syntax right.

Nov 26 2013

How do you use linq to xml to find matching nodes in two different xml files

I just asked another question here and the answer was spot on.

But that addressed what was essentially a syntax problem. Now I need help with an actual resolution.

This is the same code from the previou question (fixed up and with stuff added).

XElement FILE1 = XElement.Load (@"..\FILE1.XML");
XElement FILE2 = XElement.Load (@"..\FILE2.XML");

var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                clientID=ulm.Element("ClientID").Value,
                                firstName=file1.Element("FirstName").Value,
                                lastName=file1.Element("LastName").Value
                            }                           
                        };

var orders2 = 
             from file2 in FILE2.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                clientID=ulm.Element("ClientID").Value,
                                firstName=file2.Element("FirstName").Value,
                                lastName=file2.Element("LastName").Value
                            }                           
                        };

var matchingResults = from i in orders from j in orders2 where (i.name.firstName==j.name.firstName && i.name.lastName==j.name.lastName)
                            select i;
matchingResults.Dump()     

To make it interesting I have added a ClientID to each sequence result before trying to match them up.

What I need is to know does a Player node from order EXISTS in a player node from orders2. Or does it NOT EXIST? Ideally I would also be able to CHOOSE the selection criteria for the NOT EXISTS/EXISTS check. (LastName, or FirstName && LastName, or ClientID only, etc.)

I have NO IDEA how to go about this. Thanks for your help.

Nov 25 2013

Finding Matching Nodes in two XML files using linqpad and linq to xml is finding 0 results

I have two XML files with the same schema/structure but with different data. I am trying to use Linqpad (Linq to XML) to find the differences between the two files. Here is my code...
XElement FILE1 = XElement.Load (@"..\FILE1.XML");
XElement FILE2 = XElement.Load (@"..\FILE2.XML");

var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                firstName=file1.Element("FirstName"),
                                lastName=file1.Element("LastName")
                            }                           
                        };

var orders2 = 
             from file2 in FILE2.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                firstName=file2.Element("FirstName"),
                                lastName=file2.Element("LastName")
                            }                           
                        };

var matchingResults = from i in orders from j in orders2 where (i.name.firstName==j.name.firstName && i.name.lastName==j.name.lastName)
                            select i;
matchingResults.Dump()                          
The last Dump() is returning 0 results. I KNOW there is matching data in the two files. EDIT I forgot to mention that if I dump the results of each of the queries I get results (that are very similar) for both sequences. I have also tried the approach shown here...
Compare two xml and print the difference using LINQ (which combines the files into one sequence and then does the compare) but I am geting the same result...0 results. That approach also seems to create a cartesian product on the first orders sequence. All I want is to find matching or missing nodes from the files. What am I missing here?
May 02 2012

How do you use (or can you use) the Linq Intersect method on a child list member of an IEnumerable?

I am doing the following...

//first I have a list of sports...
List<string> sports = new List<string> {"football","basketball"}

//then I have a list of partners who are offering that sport
List<Partner> = Partner.GetAvailablePartners();

//Partner is a type that has a List<string> Sports members.

Now what I want to do is filter my list of Partners so that only partners who are offering the sports contained in sports but I can't figure out how.

I thought could use the Intersection extension method like this...

var filteredPartners = (List<Partner>) (from p in partners where p.Sports.Intersect(sports).Count()>0 select p);

but I it doesn't work I guess because I am acting on a member list not the root list.

Can this be done with the intersect (or some other linq) method?

Seth

Sep 24 2010

Fellow Netflix customer – need help deciding your next Instant Watch? Excel to the rescue. And how I did it.

I am a movie fanatic.  I think movies are serious art and movie-watching is my number one hobby. 

So Netflix is a good fit for me.  And our family watches far more movies using Instant Watch than we do with Blue-Ray and DVD disks.

But in my opinion Netflix has one major weakness.  IT does VERY LITTLE to help you SELECT your next movie.  And I am indecisive which create in me a a little perfect storm of frustration when I am in the mood for a flic.  No kidding, I have spend half the length of a typical movie just trying to FIND the right movie.  

I like to consider a lot of things when I want pic a flix…

  • What GENRE am I in the mood for or is appropriate for the audience?
  • Given the audience (frequently my wife and/or family) what is the MPAA RATING of the movie? 
  • What is the AVERAGE USER RATING of the movie?  (Help me find one that generally doesn’t suck.)

If you want to sort or filter using these criteria it is very difficult. 

To solve this problem I created an Excel spreadsheet to help.  It list the top 30 movies by GENRE sorted by AVERAGERATING in descending order.   Using this you could use the filtering capability of Microsoft Excel to find any movie you want by by Genre, MPAA Rating, and/or User Rating.  

I created an Office 2007 version and an Office 2003 version.  Here they are:

Office 2007 version.

Office 2003 version.

NOW THE TECHNICAL STUFF

To create this spreadsheet I used a FREE awesome querying tool called LinqPad.  You can get it at http://www.linqpad.net/.  After downloading (notice you don’t have to install it…tt is an executable you can put on your desktop.) Put the following C# Linq statements into a new query. 


var genre = "Thrillers";  
var minRating = 3.0;  
var topNum = 30;  

var query =  
    (from g in Genres  
    from t in g.Titles  
    where g.Name==genre  
    && t.Instant.Available==true  
    && t.AverageRating >= minRating   
    orderby t.AverageRating descending   
    select new {t.Name, 
        t.Rating, 
        t.AverageRating, 
        t.ShortSynopsis, 
        Genre=genre}  
    ).Take(topNum);  
    
query.Dump(string.Format("Top {0} {1} Instant Watch Movies with a " +  
                    "{2:0.0} minimum average rating sorted " +  
                    "by average rating in descending order.",  
                    topNum,genre,minRating));  
                    

Be sure that the Language setting is set to “C# Statement(s)” and that the Database is set to “http://odata.netflix.com/Catalog/”.  That is the OData data source that Netflix provides.

Notice that the query can only return results for one Genre at a time.  (That is a limitation of the OData data source.  There are other Netflix Data source types that are not as limiting, but you can’t use those directly in LinqPad without writing a full program.  )  So I had to run the query once for each Genre and aggregate the results into a single spreadsheet.  It took me about an hour.  Keep in mind that the data in the spreadsheet will go stale (as movies are moved out of Instant Watch and new movies are moved in.)  With this LinqPad query you can refresh the data for the genres that interest you the most.

Enjoy.

Seth

Sep 23 2010

With LINQ how do you return a string const in the result from the select operator

In LinqPad I have the following query statements...

var genre = "Anime & Animation";
var minRating = 3.0;
var topNum = 30;

var query = 
    (from g in Genres
    from t in g.Titles 
    where g.Name==genre
    && t.Instant.Available==true
    && t.AverageRating >= minRating
    orderby t.AverageRating descending 
    select new {t.Name, t.Rating, t.AverageRating, t.ShortSynopsis}).Take(topNum);

query.Dump(string.Format("Top {0} {1} Instant Watch Movies with a {2:0.0} minimum average rating sorted by average rating in descending order.",topNum,genre,minRating));

I want to return the genre string variable in the result set.

Another way to ask, with TSQL I would do "SELECT field1, field2, 'Action & Adventure' as genre from MyTitles". So how do you do that in Linq.

Seth

Sep 18 2010

How do I use linq to do a WHERE against a collection object (using Netflix data source)

I am using LinqPad to learn Linq by querying the NetFlix OData source.

(BTW I know their is a similar question already on SO...didn't help me).

Here is the query I got working which is awesome.

from x in Titles
//where x.Rating=="PG"
where x.Instant.Available==true
where x.AverageRating>=4.0
//where x.Rating.StartsWith("TV")
//where x.Genres.First (g => g.Name.Contains("Family") ) //(from y in Genres where y.Name.Contains("Family") select y)
//where x.Genres.First (g => g.Name=="")
//orderby x.Name
orderby x.AverageRating descending
//select x
//)
select new {x.Name, x.Rating, x.AverageRating, x.ShortSynopsis}

(Pardon all the comments...it is a testament to the fact I am experimenting and that I will change the query for various needs).

There are two thing I cannot figure out.

First. Let's say I only want to return the first 10 results.

Second (and most importantly). I want to filter by a partial string of the genre. Each title contains a Genres collection. I want to show only Genres where the Name contains a certain string (like "Family"). Even better filter using Titles where genre.name.contains "firstFilter" AND "secondFilter".

Basically, I want to filter by genre(s) and I cannot figure out how to do it since Title contains its own Genres collection and I cannot figure out how to return only title that are in one or more genres of the collection.

Thanks for your help!

ps...it seems that Netflix OData source does not support Any operator.

Seth