Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# have anything comparable to Python's list comprehensions?

Tags:

I want to generate a list in C#. I am missing python's list comprehensions. Is there a C# way to create collections on the fly like list comprehensions or generator expressions do in python?

like image 951
minty Avatar asked Nov 27 '08 05:11

minty


People also ask

Does C have do-while?

The C do while statement creates a structured loop that executes as long as a specified condition is true at the end of each pass through the loop.

What is || in C programming?

Logical OR operator: || The logical OR operator ( || ) returns the boolean value true if either or both operands is true and returns false otherwise. The operands are implicitly converted to type bool before evaluation, and the result is of type bool .


2 Answers

If you are using C# 3.0 (VS2008) then LINQ to Objects can do very similar things:

List<Foo> fooList = new List<Foo>(); IEnumerable<Foo> extract = from foo in fooList where foo.Bar > 10 select Foo.Name.ToUpper(); 
like image 192
Matt Campbell Avatar answered Sep 17 '22 12:09

Matt Campbell


Matt has mentioned query expressions. These are available for LINQ in general, by the way - not just LINQ to Objects. (For example, the same query applied to a LINQ to SQL datacontext would execute the filter and projection on the database.)

The query expressions in C# 3 are simply syntactic sugar over writing normal C# code - although query expressions usually end up calling extension methods. (They don't have to, and the compiler doesn't care, but they usually do.) There are various things you can do with collections which aren't available in C# query expressions, but which are supported by method calls, so it's worth being aware of both kinds of syntax. For instance, Matt's query expression of:

List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = from foo in fooList where foo.Bar > 10 select foo.Name.ToUpper(); 

is "pre-processed" into:

List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = fooList.Where(foo => foo.Bar > 10)                                      .Select(foo => foo.Name.ToUpper()); 

If you want to (say) filter based on the index of the value in the original collection, you can use an appropriate overload of Where which is unavailable via query expressions:

List<Foo> fooList = new List<Foo>(); IEnumerable<string> extract = fooList.Where((foo, index) => foo.Bar > 10 + index)                                      .Select(foo => foo.Name.ToUpper()); 

Or you could find the length of the longest name matching the criteria:

List<Foo> fooList = new List<Foo>(); int longestName = fooList.Where((foo, index) => foo.Bar > 10 + index)                          .Select(foo => foo.Name)                          .Max(); 

(You don't have to do the projection and max in separate methods - there's a Max overload which takes a projection as well.)

My point is that using extension methods you can very easily build up sophisticated queries.

You mention Python generators as well - C# has this in the form of iterator blocks. Indeed, these are incredibly useful when implementing LINQ-like operators. (Because most of LINQ to Objects is based on extension methods, you can add your own operators which look "native" to LINQ - although you can't change the query expression syntax yourself.)

like image 21
Jon Skeet Avatar answered Sep 16 '22 12:09

Jon Skeet