Browse by Tags

All Tags » LINQ (RSS)

Flattening a Jagged Array with LINQ

Today I had to flatten a jagged array .  In my case, it was a string[][] and I needed to make sure every single string contained in that jagged array was set to something (non-null and non-empty).  LINQ made the flattening very easy.  In fact, I ended up making a generic version that I could use to flatten any type of jagged array (assuming it's a T[][]): private static IEnumerable<T> Flatten<T>(IEnumerable<T[]> data) { return from r in data from c in r select c; } Then, checking to make sure the data was valid, was easy: var flattened = Flatten(data); bool isValid = !flattened.Any(s => String.IsNullOrEmpty(s)); You could even use method grouping and reduce the validation to: bool isValid = !flattened.Any(String.IsNullOrEmpty); Technorati Tags: .NET , LINQ , Jagged Array

Lookups vs. Dictionaries

Donn Felker has a great post that explains the different uses of LINQ's ToLookup and ToDictionary .  Check it out! Technorati Tags: .NET , LINQ
Posted by Patrick Steele's .NET Blog
Filed under: ,

Looking Forward to 2010

Yes, the first month of 2010 is almost gone and I'm just now getting around blogging about the past year and the year ahead.  I guess time management should be on my to-do list for this year? The CodeMash Website One of the coolest projects I've worked on in 2009 was the CodeMash website .  Brian Prince and Jim Holmes asked SRT if they wanted to help design a new website for CodeMash.  Brian will be the first to admit that he's an evangelist first, a developer second and a web developer third.  They gave us pretty much free reign to come up with a new idea as well as the freedom to implement the solution however we wanted. We worked with a Inner Circle Media to help plan the new look and feel of the site.  They deserve kudos for the new look.  On the back-end, I used ASP.NET MVC 1.0 along with SQL Server, Linq2SQL and Castle Windsor for my IoC container.  We also integrated with the existing Sharepoint installation for sponsor maintenance, news and session submissions.  User registration was all done in SQL. This was a great learning project.  Registering for a conference is usually a simple process (from the registrants standpoint).  On the back-end, when you're dealing with varying registration costs (based on the current date), discount codes, PayPal, and other things, it can get pretty complicated.  A large suite of unit tests helped us catch a lot of stuff in the beginning, but a few bugs slippped through.  Luckily, nothing major! I want to also thank fellow SRT developers Marina Fedner and Ben Barefield .  Marina helped me out on the user registration portion and Ben was responsible for the REST feed that we all used for our mobile CodeMash applications . Stepping Down from GANG After being involved with the Great Lakes Area .NET Users Group (GANG) for many, many years (webmaster, VP and this last year as President), I did not run for re-election.  There were some other projects I was taking on and last year's vice president David Giard was willing to take the reigns of the group.  Dave did an amazing job last year as VP and is continuing to do great things with GANG in 2010 .  I'll still be around to help out from time to time, but Dave is the man in charge now! VSM's C# Corner After helming Visual Studio Magazine's C# Corner for a number of years, Bill Wagner decided he wanted to devote his time to other things.  He offered my name as a possible successor!  I talked it over with him and VSM Editor in Chief Michael Desmond.  Everything fell into place and I'm now honored to be following in Bill's footsteps as a VSM author.  My first column has been published ( Interface-Based Programming in C# ) and I've got some positive feedback so far.  My next article is in-process and I have to have the first draft done by February 1st or I'll be on someone's naughty list (and it won't be Santa's!). Microsoft C# MVP I was pleasantly surprised on January 1st to receive an email from Microsoft telling me I've received an MVP award for my C# and community work in 2009.  Thanks to Microsoft and other community members I work closely with! 2010 Plans One of the big conferences for 2010, CodeMash , has already come and gone.  It was a great conference and you CAN NOT beat the price.  The amount of content and learning available is unheard of for the price you pay.  I'm already looking forward to CodeMash 2.0.1.1. In February, I'll be attending the MVP Summit in Redmond.  A great chance to get in touch with new technologies, talk with Microsoft reps and mix it up with other MVP's. Michael Eaton is already planning this year's Ann Arbor Give Camp .  I've offered my assistance again this year and will post more on this even as it gets closer. Speaking: I'd like to do more speaking this year.  While I usually get compliments on my presentations, I'm very hard on myself.  I may be a good speaker, but I want to be a great speaker.  That will come with practice.  I've got some idea's for presentations on topics I'm passionate about (specifically, Inversion of Control and Mocking). I'm really looking forward to 2010! Technorati Tags: SRT , MVP , CodeMash , 2010

LINQ and Homework

My daughter asked me to check her homework today.  One of the math problems was: A book has 352 pages.  How many 4's were used to print all of the page numbers. She got 35.  She explained how she arrived at that number and while her logic was good, it sounded too low to me.  I started thinking about it a little and then decided I could just write a few lines of C# code to figure out the answer. As Visual Studio was starting up, I pictured the code in my head: initialize a counter to zero.  Loop through an int from 1 to 352 and see if the ToString() contains a 4.  If so, increase the counter.  Just as I was about to start typing, I thought, "Oh wait – I could do all of this with LINQ!". var answer = Enumerable.Range(1, 352).Count(p => p.ToString().Contains( "4" )); How did we ever manage before LINQ?  ;) Technorati Tags: .NET , LINQ , Homework
Posted by Patrick Steele's .NET Blog
Filed under: , ,

LINQ2SQL: SubmitChanges() doesn't do anything?

Dear Linq2SQL, I'm sorry.  It was a mistake.  I was just doing a simple demo and forgot to define the primary key on a table.  You were so nice to generate my class definitions for me without complaining.  You queried the data and gave it to me without incidence.  You even let me update the object and submit my changes. But since I forgot to define a primary key for the table, YOU IGNORED ME!  Kind of harsh, in my opinion.  You could have at least given me some kind of an error or something letting me know you had no way to update the table.  During debugging, I asked you for your ChangeSet and you simply told me: 0 Deletes, 0 Creates, 0 Updates.  While that information is correct, it's not very helpful. Signed, A developer who would like the last hour back… Technorati Tags: LINQ , LINQ2SQL
Posted by Patrick Steele's .NET Blog
Filed under: , ,

Comparing Two Arrays

I was looking at some old code today that was checking if two byte arrays had the same data in them.  It was a simple loop that compared each element.  I recalled my blog post from November of last year about comparing collections/arrays in MSTest and thought, "I wonder if LINQ has something similar"? As a matter of fact it does!  IEnumerable<T>.SequenceEqual() does exactly what I was looking for.  By default, it uses the type's default comparer, or you can supply your own.  Very nice! Technorati Tags: .NET , LINQ
Posted by Patrick Steele's .NET Blog
Filed under: ,

LINQ: Quickly Create Dictionaries with ToDictionary

Donn Felker recently blogged about a neat little extension method in LINQ called Any() .  If you simply want to know if a sequence contains any elements, many people use ".Count() > 0" which will walk the entire sequence to compute the count whereas .Any() will stop walking as soon as it finds a single element.  Easy and much more efficient. It reminded me about another LINQ method I've used from time to time: ToDictionary().  This method will allow you to quickly create a dictionary from any IEnumerable<T>.  Let's start with some sample data that is in a List<T>: IList<Person> people = new List<Person> { new Person {FirstName = "Bob" , LastName = "Smith" , SSN = "1" }, new Person {FirstName = "Jane" , LastName = "Doe" , SSN = "2" }, new Person {FirstName = "Mike" , LastName = "Johnson" , SSN = "3" } }; Converting this to a dictionary is pretty trivial without LINQ.  Suppose we want to index these by SSN: var d = new Dictionary< string , Person>(); foreach (var p in people) { d.Add(p.SSN, p); } But why waste our time doing all that when we can simply use LINQ's ToDictionary()?  Just give it a lambda that selects the key and you're all set: var indexedBySSN = people.ToDictionary(k => k.SSN); Or perhaps you don't want the entire Person object.  Maybe you just want a collection of last names indexed by Social Security Number (SSN).  No problem --there's an overload that accepts two lambdas: one to select the key and one to select the value. var lastNamesIndexedBySSN = people.ToDictionary(k => k.SSN, e => e.LastName); There's also two more overloads that work the same as the two above, but allow you to also provide an IEqualityComparer<T> used to compare your keys. Everyday I find more and more stuff in LINQ that helps me eliminate the mundane code and make my source more readable. Technorati Tags: .NET , LINQ
Posted by Patrick Steele's .NET Blog
Filed under: ,

Getting Func-y with Lambdas

Let's say we've got some information stored somewhere (database, XML, file – it doesn't matter) about individuals.  For simplicity, let's look at a class that represents this data: 1: class Person 2: { 3: public string FirstName { get; set; } 4: public string LastName { get; set; } 5: public string EmailAddress { get; set; } 6:   7: public static Person FindByEmailAddress( string emailAddress) 8: { 9: // implementation omitted 10: } 11:   12: public void Save() 13: { 14: // implementation omitted 15: } 16: } We've got some exported CSV data that needs to be merged into this set of data.  However, the information from the CSV file has multiple email address' per person.  Here's the class that represents each row of CSV data: 1: class CSVData 2: { 3: public string FirstName { get; set; } 4: public string LastName { get; set; } 5: public string HomeEmail { get; set; } 6: public string WorkEmail { get; set; } 7: } Some people in the CSV data will have only a home email, some will have only a work email, and some will have both.  I can easily get a couple of lists that contain the people with email address' defined via LINQ (note: the implementation of LoadCSVData is not important here): 1: IList<CSVData> csvData = LoadCSVData(); 2: var peopleWithHomeEmail = from c in csvData where c.HomeEmail.Length > 0 select c; 3: var peopleWithWorkEmail = from c in csvData where c.WorkEmail.Length > 0 select c; Now I want to loop through each list, see if the email address is already in our current data store and add ones that are not. 1: UpdateEmails(peopleWithHomeEmail); 2: UpdateEmails(peopleWithWorkEmail); A simple implementation of UpdateEmails might look like this: 1: private void UpdateEmails(IEnumerable<CSVData> list) 2: { 3: foreach (var dataItem in list) 4: { 5: Person person = Person.FindByEmailAddress(dataItem.HomeEmail); 6: if (person == null ) 7: { 8: person = new Person() 9: { 10: FirstName = dataItem.FirstName, 11: LastName = dataItem.LastName, 12: EmailAddress = dataItem.HomeEmail 13: }; 14: person.Save(); 15: } 16: } 17: } The obvious problem with this is that it always accesses the HomeEmail address field from the CSVData.  What's going to happen when I pass "peopleWithWorkEmail" to this method?  Not good. Delegates To The Rescue This is the perfect place for a delegate. We'd like to have some function that accepts a CSVData object and returns a string – either home email or work email: 1: private delegate string GetEmailAddress(CSVData data); Now we can re-write our UpdateEmails method to accept a delegate that will determine which email address we'll grab: 1: private void UpdateEmails(IEnumerable<CSVData> list, GetEmailAddress getEmail) 2: { 3: foreach (var dataItem in list) 4: { 5: Person person = Person.FindByEmailAddress(getEmail(dataItem)); 6: if (person == null ) 7: { 8: person = new Person() 9: { 10: FirstName = dataItem.FirstName, 11: LastName = dataItem.LastName, 12: EmailAddress = getEmail(dataItem) 13: }; 14: person.Save(); 15: } 16: } 17: } Thanks lambdas, we can make the calling code very clean: 1: UpdateEmails(peopleWithHomeEmail, p => p.HomeEmail); 2: UpdateEmails(peopleWithWorkEmail, p => p.WorkEmail); A very clean solution.  Except… Delegate Maintenance The only issue with this is now we have a delegate sitting around just for this simple lambda expression.  At some point in time, we may want to do some date calculations from data found inside CSVData.  If we had multiple dates to pick from (like multiple emails in this situation), we may have to create another delegate that accepts a CSVData and returns a DateTime.  What we need is a generic way of defining a method that accepts some data type(s) and returns a specific data type (note emphasis on generic !). Since this is such a common scenario, Microsoft has pre-defined a bunch of generic delegates that do exactly what we need. Getty Func-y Here's what you can use from System.Core: Func<TResult> – This delegate takes no parameters and simply returns an object of type TResult Func<T, TResult> – Just like Func<TResult>, but this one accepts a single parameter (T).  This is exactly the situation we have in our example. Microsoft also defines three other Func<> delegates – one that accepts 2 parameters, one that accepts 3 and finally, one that accepts 4.  Anything more than four and you'd have to define your own Func<> delegate. We can now get rid of our GetEmailAddress delegate and replace it with a Func<CSVData, string> (which is the exact same signature – a method that accepts a CSVData and returns a string): 1: private void UpdateEmails(IEnumerable<CSVData> list, Func<CSVData, string > getEmail) Our calling code doesn't need to change at all.  We're still using the same signature, so the C# compiler can infer the delegate...
Posted by Patrick Steele's .NET Blog
Filed under: , ,

LINQ: Grabbing a single element

Since I've seen code like this before and am also guilty of writing code like this, I thought I'd blog about an easier way to grab a single element from a LINQ query that Bill Wagner told me about at last night's AADND meeting. Consider the following class: 1: public class Person 2: { 3: public string Name { get; set; } 4: public int Age { get; set; } 5: public bool Leader { get; set; } 6: } And let's load up some sample data: 1: Person[] people = new Person[] { 2: new Person { Name = "Blue" , Age = 25, Leader = true }, 3: new Person { Name = "Gold" , Age = 16, Leader = false }, 4: new Person { Name = "Red" , Age = 27, Leader = false }, 5: new Person { Name = "Green" , Age = 14, Leader = false } 6: }; Now what we could do to find the leader (the assumption is that there is always only one leader): 1: Person leader = people.Where(p => p.Leader == true ).ToArray()[0]; The result of the people.Where() is an IEnumerable<Person>.  And you can't just index the first element of that – so you convert it to an array and index that instead. LINQ provides two methods to perform this type of query without the need of having an intermediate array -- "First" and "Single": 1: Person leader2 = people.First(p => p.Leader == true ); 2: Person leader3 = people.Single(p => p.Leader == true ); The difference between the two is that First grabs the first item it finds.  The Single method expects only a single matching item and will throw an exception if it finds more than one.  In this case, there is only one Person in the array that has Leader set to true so both of these lines of code produce the same result. However, in the situation below: 1: Person firstChild1 = people.First(p => p.Age < 18); 2: Person firstChild2 = people.Single(p => p.Age < 18); The first line will succeed.  The second line will fail since there are two people that are under 18. Technorati Tags: .NET , LINQ
Posted by Patrick Steele's .NET Blog
Filed under: ,

Project Euler #14

I had so much fun doing #13 I thought I'd tackle #14 as well. This problem wasn't too bad.  I started by defining some extension methods on long: 1: static class Extensions 2: { 3: public static long NextInSequence( this long number) 4: { 5: if (number % 2 == 0) 6: { 7: return number / 2; 8: } 9: else 10: { 11: return 3 * number + 1; 12: } 13: } 14:   15: public static IList< long > GenerateSequence( this long number) 16: { 17: List< long > seq = new List< long >(); 18:   19: long next = 0; 20: do 21: { 22: next = number.NextInSequence(); 23: seq.Add(next); 24: number = next; 25: } while (next != 1); 26:   27: return seq; 28: } 29: } While I don't necessarily need the full list of terms (GenerateSequence), I used the list in testing to make sure my sequence logic was correct. Now, the only thing left to do was to find the longest sequence.  I used a LINQ query to order the list of sequence counts in descending order so the longest would be at the top: 1: var range = Enumerable.Range(1, 1000000); 2:   3: var biggest = (from n in range 4: let size = (( long )n).GenerateSequence().Count 5: orderby size descending 6: select new { Number = n, Length = size }).ToArray(); 7:   8: Console.WriteLine( "{0} has a sequence of {1}" , biggest[0].Number, biggest[0].Length); Technorati Tags: Project Euler , .NET , LINQ

Project Euler #13

It's been a while since I did one of the Project Euler problems.  And since a lot of my work recently has been fixing bugs and working on some design documents, I was itching to do some "real" coding.  So it's on to problem #13 . Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. It would be nice if I could have stuck all of those numbers in an integer and simply added them up, but they were too big for that.  The solution I came up with kind of feels like I cheated a bit, but it gives me the correct answer!  What I did was take the list of 50-digit numbers and stick a decimal point in the middle (at the 25th character).  This gives me a number that .NET's double data type can handle.  I just had to make sure I removed the decimal point before grabbing my answer. So my final solution was: 1: string [] numbers = { 2: // giant list of numbers from website clipped 3: }; 4:   5: var list = from num in numbers 6: select double .Parse(num.Insert(25, "." )); 7:   8: var sum = list.Sum(); 9: string answer = sum.ToString().Replace( "." , "" ).Substring(0, 10); Technorati Tags: Project Euler , .NET , LINQ