One of the most beloved C# 3.0 features is Linq. Linq brings great power to C#, it allows you to easily write structured queries over collections or remote data sources. Now with C# is possible to make queries as easy as with other languages like Python. I decided to compare the way you make queries with C# and with Python. I found a great page showing 101 Linq examples, I decided to write Python versions of this examples. Which version do you like more?
C# version:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var lowNums = from n in numbers where n < 5 select n;
Python version:
numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0] low_nums = (n for n in numbers if n < 5)
C# version:
string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; var shortDigits = digits.Where((digit, index) => digit.Length < index);
Python version:
digits = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'] short_digits = (digit for index, digit in enumerate(digits) if len(digit) < index)
C# version:
var numsPlusOne = from n in numbers select n + 1;
Python version:
nums_plus_one = (n + 1 for n in numbers)
C# version:
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" }; var upperLowerWords = from w in words select new {Upper = w.ToUpper(), Lower = w.ToLower()};
Python version:
The exact Python version would be something like:
words = ['aPPLE', 'BlUeBeRrY', 'cHeRry'] upper_lower_words = ( type('', (), {'upper': w.upper(), 'lower': w.upper() }) for w in words)
But I feel more Pythonic this:
upper_lower_words = ( (w.lower(), w.upper()) for w in words)
Or even this:
upper_lower_words = ( {'upper': w.upper(), 'lower': w.upper() } for w in words)
C# version:
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; int[] numbersB = { 1, 3, 5, 7, 8 }; var pairs = from a in numbersA, b in numbersB where a < b select new {a, b};
Python version:
numbersA = [0, 2, 4, 5, 6, 8, 9] numbersB = [1, 3, 5, 7, 8 ] pairs = ( (a, b) for a in numbersA for b in numbersB if a < b)
C# version:
var orders = from c in customers, o in c.Orders, total = o.Total where total >= 2000.0M select new {c.CustomerID, o.OrderID, total};
Python version:
I couldn’t find how to make the assignment in Python, so the version is:
orders = ( {'customer_id': c.customer_id, 'order_id': o.order_id, 'total': o.total } for c in customers for o in c.orders if o.total > 2000)
C# version:
var orders = from c in customers
where c.Region == "WA"
from o in c.Orders
where o.OrderDate >= cutoffDate
select new {c.CustomerID, o.OrderID};
Python version:
orders = ( (c.customer_id, o.order_id) for c in customers if c.region == 'WA' for o in c.orders if o.date >= cutoff_date)
C# version:
var first3Numbers = numbers.Take(3);
Python version:
if we are working with something like a list, we could do:
first_3_numbers = numbers[:3]
but, if we are working with iterators, we must do:
first_3_numbers = itertools.islice(numbers, None, 3)
C# version:
var allButFirst4Numbers = numbers.Skip(4);
Python version:
all_but_fist_4_numbers = numbers[4:] # list version all_but_fist_4_numbers = itertools.islice(numbers, 4, None) # iterator version
C# version:
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Python version:
fist_numbers_less_that_6 = itertools.takewhile(lambda x: x < 6, numbers)
C# version:
var allButFirst3Numbers = numbers.SkipWhile(n => n % 3 != 0);
Python version:
all_but_first_3_numbers = itertools.dropwhile(lambda x: x % 3 != 0, numbers)
C# version:
numbers.First() numbers.Last()
Python version:
numbers[0] # first for a list numbers[-1] # last for a list numbers.next() # first for iterator list(numbers)[0] # first for iterator list(numbers)[-1] # last for iterator
C# version:
int evenNum = numbers.First((num, index) => (num % 2 == 0) && (index % 2 == 0));
Python version:
even_num = [n for i, n in enumerate(numbers) if n%2 == 0 and i%2 == 0][0]
or:
even_num = (n for i, n in enumerate(numbers) if n%2 == 0 and i%2 == 0).next()
to be continued…