list-comprehension and map question (simple)

Brian van den Broek bvande at po-box.mcgill.ca
Sun Mar 27 14:41:28 EST 2005


Brian van den Broek said unto the world upon 2005-03-27 14:12:
> Charles Hartman said unto the world upon 2005-03-27 13:35:
> 
>> On Mar 27, 2005, at 1:18 PM, Brian van den Broek wrote:
>>
>>> >>> def some_arbitrary_function(y):
>>> ...     return ( (y * 42) - 19 ) % 12
>>> ...
>>> >>> [some_arbitrary_function(len(x)) for x in lines.split()]
>>> [5, 5, 11, 11, 5, 11, 5, 11]
>>> >>>
>>>
>>>
>>> I could be missing some edge cases, but it seems to me that if you 
>>> have list comps you don't really need map, filter, and the like. The 
>>> map portion can be done by nested function applications in the list 
>>> comp itself.
>>
>>
>>
>> A good point, and I think I see that. But ultimately what I'm 
>> wondering is whether a construction like this [1]:
>>
>>         for s in possScansions:
>>             for a in algorithms:
>>                 (feet, test) = self.DoAlgorithm(a, s)
>>                 complexities[(s, a)] = (self._measureComplexity(feet, 
>> test), len(feet))
>>
>> can be condensed in one or more of these ways. (Whether the result 
>> would be readable / maintainable is a separate question. So is whether 
>> it would be more efficient. At the moment I'm just trying to get clear 
>> about the syntax.)
>>
>> [1] possScansions is a list of strings; algorithms is a list of ints; 
>> feet is a list of strings; test is a list of Booleans. complexities is 
>> a dictionary whose keys are those two-item tuples and whose values are 
>> the integers returned by self._measureComplexity
>>
>> Charles Hartman
> 
> 
> Hi Charles,
> 
> Is the code below the sort of thing you had in mind?
> 
> (I should be quite upset if I actually came across such code in the wild.)
> 
>  >>> # set-up with arbitrary functions, etc.
>  >>> string_list = ['a', 'list of', 'arbitrary', 'strings']
>  >>> int_list = [3, 5, 42]
>  >>> def some_function(a, s):
> ...     if len(a) > s:
> ...         chunk = a[s:]
> ...     else:
> ...         chunk = None
> ...     return len(a) > s, chunk
> ...
>  >>> def another_function(x, y):
> ...     if y:
> ...         return x + len(y)
> ...     else:
> ...         return x
> ...
>  >>> complexities = {}
>  >>> simpler = {}
>  >>> # The structure you have above -- modulo that I flipped
>  >>> # the order of arguments in the first function due to
>  >>> # inattention (it doesn't matter, though).
>  >>> for s in string_list:
> ...     for i in int_list:
> ...         (feet, test) = some_function(s, i)
> ...         simpler[(s, i)] = another_function(feet, test)
> ...
>  >>> # The evil way:
>  >>> # (Please don't do this, at least IMHO)
>  >>> for t in [(s, i, another_function(*some_function(s, i))) for s in 
> string_list for i in int_list]:
> ...     complexities[(t[0], t[1])] = t[2]
> ...
>  >>> simpler == complexities
> True
>  >>>
> 
> I've not the glimmer of a clue which would be faster, and don't care to 
> check -- the evil way could be 5 times faster, and I wouldn't want it in 
> my code :-)

Sorry for the self-reply, but I just saw how to crank the evil up a 
notch, and get it as a one-liner to boot:

 >>> complexities = {}
 >>> side_effect_list = [complexities.__setitem__((s, i), 
another_function(*some_function(s, i))) for s in string_list for i in 
int_list]
 >>> simpler == complexities
True
 >>> side_effect_list
[None, None, None, None, None, None, None, None, None, None, None, None]
 >>>

Best,

Brian vdB




More information about the Python-list mailing list