List Comprehensions and MySQL's GROUP_CONCAT

May 13, 2008 11:39

List Comprehensions
The more time I spend with Python, the more I come to like it. The latest in the list (no pun intended) of likable Python-foo is List Comprehensions. What's that? We'll come to it in a bit but now for some background building ( Read more... )

listcomprehensions, programming, comprehensions, mysql, python, sql, code, groupconcat

Leave a comment

Comments 13

sunson May 13 2008, 11:29:52 UTC
And before I end this post, let me repeat. I HATE Java. Hate it absolutely totally, because it sucks the life blood out of me when I have to write code that I know can be 10x more succinct in another language.

I can bet, the 'another language' in question is a post-java-era language (ex: Python, Ruby). I think java has opened up the world's eyes on creating languages that allow you to focus on the problem at hand than on programming.

PS: I hate java too, for other reasons of how it is 'mind altering' - on how people tend to forget to tread the path of simply trying to model the real world in a computer program and instead start twisting their own thinking patterns in order to get a working program out... And all I see are decrepit programmers who are the victims of the java-thought-process. They can no longer think straight. In their world, Verbs are extinct.

Reply

code_martial May 13 2008, 11:58:30 UTC
I can bet, the 'another language' in question is a post-java-era language (ex: Python, Ruby). I think java has opened up the world's eyes on creating languages that allow you to focus on the problem at hand than on programming.

Perl and Lisp pre-date Java. Python has been around for longer than you think [#]. I don't understand what you mean in the second sentence about Java allowing you to focus on the problem at hand or other languages stopping you from doing so.

BTW, the post that you linked to is the same as the one I linked to. Not sure if that was intentional.

Reply


cross product t3rmin4t0r May 13 2008, 13:30:35 UTC
Recently, I was helping someone generate random combinations of options (for generating messages for tests) in python

mcross = \
lambda ss, row=[]: \
(len(ss) > 1 and \
reduce(lambda x,y: x + y, map(lambda each: mcross(ss[1:], row + [each]), ss[0]),[])) \
or (map(lambda each: row + [each], ss[0])

print mcross([[1,2],[3,4]])
totally warped, but as Horace said "It is when I struggle to be brief that I become obscure"

And yes, I prefer python's map/reduce/filter, because of how nicely it plays into alternative syntaxes

Reply

Re: cross product code_martial May 14 2008, 02:24:48 UTC
So why does it take so much of weird code to just do a cross-product? I couldn't figure out the exact stuff that was going on there, but my guess is that:

a) you need to handle the case where ss has zero or one elements since reduce crashes in the former case and fails to invoke the function passed to it as the first parameter in the latter case.
b) you also need to pass around the intermediate result to recursive calls.
c) you replace a function definition with an assignment to an anonymous function. I'm not sure if that's such a bright idea.
d) you replace if/else with and/or, relying on the short-circuit evaluation to do the Right Thing™. That's borderline obfuscation, methinks. I use it too, sometimes, but I wouldn't have used it above.

The List Comprehension version is clearly more brief and less obscure. If you still want to do it the recursive way, there's yield to help you keep the intermediate result around. I started using lambdas and map extensively but quickly gave them up in favour of comprehensions because lambda ( ... )

Reply

Brief? code_martial May 14 2008, 02:59:26 UTC
t3.py

mcross = \
lambda ss, row=[]: \
(len(ss) > 1 and \
reduce(lambda x,y: x + y, map(lambda each: mcross(ss[1:], row + [each]), ss[0]),[])) \
or (map(lambda each: row + [each], ss[0])

print mcross([[1,2],[3,4]])
6 non-blank lines, 175 non-space characters. Max line-length: 95

codie.py

def mcross(ss):
if len(ss) == 1:
return [[x] for x in ss[0]]
else:
return [[x] + y for x in ss[0] for y in mcross(ss[1:])]

print mcross([[1,2],[2,3]])
6 non-blank lines, 124 non-space chars. Max line-length: 63

Do I win?

Reply

Re: Brief? t3rmin4t0r May 14 2008, 18:40:46 UTC
Oddly, I didn't think that would work with python 2.3.

And I have a weak spot for map/reduce, especially since my original code turns out to be practically identical to the lisp equivalent.

And slowly, I'm training myself to lose the "branch/loop" C-style semantics from my head so that I can start writing GPU style conditional-write pipeline-full code. It requires a lot of unlearning, from what I've realized (see the and/or short-circuiting, for instance).

Reply


bluesmoon May 15 2008, 11:12:37 UTC
remember that , is not a universal list separator.

Reply

code_martial May 15 2008, 13:09:11 UTC
So?

Reply

bluesmoon May 15 2008, 13:12:31 UTC
it's something that has to be internationalised, hence should not be generated at the database level/as part of your back end logic. This is something that needs to be done at your front end based on the intl that you're serving.

Reply

code_martial May 15 2008, 13:22:41 UTC
What if there's no front-end in question?

Reply


Leave a comment

Up