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?
Where – Simple 1
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)
Where – Indexed
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)
Select – Simple 1
C# version:
var numsPlusOne = from n in numbers select n + 1;
Python version:
nums_plus_one = (n + 1 for n in numbers)
Select – Anonymous Types 1
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)
SelectMany – Compound from 1
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)
SelectMany – from Assignment
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)
SelectMany – Multiple from
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)
Take Simple
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)
Skip – Simple
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
TakeWhile – Simple
C# version:
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Python version:
fist_numbers_less_that_6 = itertools.takewhile(lambda x: x < 6, numbers)
SkipWhile – Simple
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)
First & Last
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
First – Indexed
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…
You must be logged in to post a comment.