Suppose I have a list of strings, A. I want to compute the list (call it B) of strings that are elements of A but doesn't match a regex. I could use a for loop to do so. In a functional language, there is way to do so without using the for loop.
I'm wondering what is the best way to compute B in python.
On Thu, Nov 5, 2009 at 8:19 PM, Peng Yu <pengyu...@gmail.com> wrote: > Suppose I have a list of strings, A. I want to compute the list (call > it B) of strings that are elements of A but doesn't match a regex. I > could use a for loop to do so. In a functional language, there is way > to do so without using the for loop.
> I'm wondering what is the best way to compute B in python.
On Thu, Nov 5, 2009 at 10:25 PM, Chris Rebert <c...@rebertia.com> wrote: > On Thu, Nov 5, 2009 at 8:19 PM, Peng Yu <pengyu...@gmail.com> wrote: >> Suppose I have a list of strings, A. I want to compute the list (call >> it B) of strings that are elements of A but doesn't match a regex. I >> could use a for loop to do so. In a functional language, there is way >> to do so without using the for loop.
>> I'm wondering what is the best way to compute B in python.
Now, I want to in-place delete elements in A that matches the regex. I know that I need to use del. But I'm not sure how to use the functional style programming for this problem. Would you please let me know?
On Thu, Nov 5, 2009 at 9:23 PM, Peng Yu <pengyu...@gmail.com> wrote: > On Thu, Nov 5, 2009 at 10:25 PM, Chris Rebert <c...@rebertia.com> wrote: >> On Thu, Nov 5, 2009 at 8:19 PM, Peng Yu <pengyu...@gmail.com> wrote: >>> Suppose I have a list of strings, A. I want to compute the list (call >>> it B) of strings that are elements of A but doesn't match a regex. I >>> could use a for loop to do so. In a functional language, there is way >>> to do so without using the for loop.
>>> I'm wondering what is the best way to compute B in python.
> Now, I want to in-place delete elements in A that matches the regex. I > know that I need to use del. But I'm not sure how to use the > functional style programming for this problem. Would you please let me > know?
Deletion is an imperative operation which has no direct equivalent in functional languages, so your question is nonsensical. To do it functionally, instead of deleting, you simply build a new list that omits the undesired elements. See also the built-in function filter().
> On Thu, Nov 5, 2009 at 10:25 PM, Chris Rebert <c...@rebertia.com> wrote: >> On Thu, Nov 5, 2009 at 8:19 PM, Peng Yu <pengyu...@gmail.com> wrote: >>> Suppose I have a list of strings, A. I want to compute the list (call >>> it B) of strings that are elements of A but doesn't match a regex. I >>> could use a for loop to do so. In a functional language, there is way >>> to do so without using the for loop.
>>> I'm wondering what is the best way to compute B in python.
> Now, I want to in-place delete elements in A that matches the regex. I > know that I need to use del. But I'm not sure how to use the > functional style programming for this problem. Would you please let me > know?
Functional and del don't mix. What about:
B = [item for item in A if regex.match(item) is None] B = filter(lambda item: regex.match(item) is None, A)
Peng Yu wrote: > Suppose I have a list of strings, A. I want to compute the list (call > it B) of strings that are elements of A but doesn't match a regex. I > could use a for loop to do so. In a functional language, there is way > to do so without using the for loop.
In functional language, there is no looping, so that argument is kind of pointless. The looping construct in many functional language is a syntax sugar for recursion.
In python, instead of explicit loop, you can use either: map(pattern.match, list_of_strs) or [pattern.match(mystr) for mystr in list_of_strs]
or if you want to be wicked evil, you can write a recursive function as such:
def multimatcher(list_of_strs, index=0): return [] if index >= len(list_of_strs) else ( multimatcher( list_of_strs[index + 1] ).append( pattern.match(list_of_strs[index]) ) )
> Suppose I have a list of strings, A. I want to compute the list (call > it B) of strings that are elements of A but doesn't match a regex. I > could use a for loop to do so. In a functional language, there is way > to do so without using the for loop.
Nonsense. For processing over each element, you have to loop over them, either with or without growing a call-stack at the same time.
FP languages can optimize away the stack-frame-growth (tail recursion) - but this isn't reducing complexity in any way.
So use a loop, either directly, or using a list-comprehension.
On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> wrote:
> Peng Yu schrieb:
>> Suppose I have a list of strings, A. I want to compute the list (call >> it B) of strings that are elements of A but doesn't match a regex. I >> could use a for loop to do so. In a functional language, there is way >> to do so without using the for loop.
> Nonsense. For processing over each element, you have to loop over them, > either with or without growing a call-stack at the same time.
> FP languages can optimize away the stack-frame-growth (tail recursion) - but > this isn't reducing complexity in any way.
> So use a loop, either directly, or using a list-comprehension.
What is a list-comprehension?
I tried the following code. The list 'l' will be ['a','b','c'] rather than ['b','c'], which is what I want. It seems 'remove' will disrupt the iterator, right? I am wondering how to make the code correct.
l = ['a', 'a', 'b', 'c'] for x in l: if x == 'a': l.remove(x)
On Fri, 6 Nov 2009, Peng Yu wrote: > On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> wrote: > > Peng Yu schrieb:
> >> Suppose I have a list of strings, A. I want to compute the list (call > >> it B) of strings that are elements of A but doesn't match a regex. I > >> could use a for loop to do so. In a functional language, there is way > >> to do so without using the for loop.
> > Nonsense. For processing over each element, you have to loop over them, > > either with or without growing a call-stack at the same time.
> > FP languages can optimize away the stack-frame-growth (tail recursion) - but > > this isn't reducing complexity in any way.
> > So use a loop, either directly, or using a list-comprehension.
> What is a list-comprehension?
> I tried the following code. The list 'l' will be ['a','b','c'] rather > than ['b','c'], which is what I want. It seems 'remove' will disrupt > the iterator, right? I am wondering how to make the code correct.
> l = ['a', 'a', 'b', 'c'] > for x in l: > if x == 'a': > l.remove(x)
> print l
list comprehension seems to be what you want:
l = [i for i in l if i != 'a']
rday --
======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA
>> On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> wrote: >> > Peng Yu schrieb:
>> >> Suppose I have a list of strings, A. I want to compute the list (call >> >> it B) of strings that are elements of A but doesn't match a regex. I >> >> could use a for loop to do so. In a functional language, there is way >> >> to do so without using the for loop.
>> > Nonsense. For processing over each element, you have to loop over them, >> > either with or without growing a call-stack at the same time.
>> > FP languages can optimize away the stack-frame-growth (tail recursion) - but >> > this isn't reducing complexity in any way.
>> > So use a loop, either directly, or using a list-comprehension.
>> What is a list-comprehension?
>> I tried the following code. The list 'l' will be ['a','b','c'] rather >> than ['b','c'], which is what I want. It seems 'remove' will disrupt >> the iterator, right? I am wondering how to make the code correct.
>> l = ['a', 'a', 'b', 'c'] >> for x in l: >> if x == 'a': >> l.remove(x)
>> print l
> list comprehension seems to be what you want:
> l = [i for i in l if i != 'a']
My problem comes from the context of using os.walk(). Please see the description of the following webpage. Somehow I have to modify the list inplace. I have already tried 'dirs = [i for i in l if dirs != 'a']'. But it seems that it doesn't "prune the search". So I need the inplace modification of list.
When topdown is True, the caller can modify the dirnames list in-place (perhaps using del or slice assignment), and walk() will only recurse into the subdirectories whose names remain in dirnames; this can be used to prune the search, impose a specific order of visiting, or even to inform walk() about directories the caller creates or renames before it resumes walk() again. Modifying dirnames when topdown is False is ineffective, because in bottom-up mode the directories in dirnames are generated before dirpath itself is generated.
Peng Yu wrote: > My problem comes from the context of using os.walk(). Please see the > description of the following webpage. Somehow I have to modify the > list inplace. I have already tried 'dirs = [i for i in l if dirs != > 'a']'. But it seems that it doesn't "prune the search". So I need the > inplace modification of list.
Peng Yu wrote: > On Fri, Nov 6, 2009 at 10:42 AM, Robert P. J. Day <rpj...@crashcourse.ca> wrote: >> On Fri, 6 Nov 2009, Peng Yu wrote:
>>> On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> wrote: >>>> Peng Yu schrieb: >>>>> Suppose I have a list of strings, A. I want to compute the list (call >>>>> it B) of strings that are elements of A but doesn't match a regex. I >>>>> could use a for loop to do so. In a functional language, there is way >>>>> to do so without using the for loop. >>>> Nonsense. For processing over each element, you have to loop over them, >>>> either with or without growing a call-stack at the same time.
>>>> FP languages can optimize away the stack-frame-growth (tail recursion) - but >>>> this isn't reducing complexity in any way.
>>>> So use a loop, either directly, or using a list-comprehension. >>> What is a list-comprehension?
>>> I tried the following code. The list 'l' will be ['a','b','c'] rather >>> than ['b','c'], which is what I want. It seems 'remove' will disrupt >>> the iterator, right? I am wondering how to make the code correct.
>>> l = ['a', 'a', 'b', 'c'] >>> for x in l: >>> if x == 'a': >>> l.remove(x)
>>> print l >> list comprehension seems to be what you want:
>> l = [i for i in l if i != 'a']
> My problem comes from the context of using os.walk(). Please see the > description of the following webpage. Somehow I have to modify the > list inplace. I have already tried 'dirs = [i for i in l if dirs != > 'a']'. But it seems that it doesn't "prune the search". So I need the > inplace modification of list.
[snip] You can replace the contents of a list like this:
Peng Yu wrote: > On Fri, Nov 6, 2009 at 10:42 AM, Robert P. J. Day <rpj...@crashcourse.ca> wrote:
>> On Fri, 6 Nov 2009, Peng Yu wrote:
>>> On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> wrote:
>>>> Peng Yu schrieb:
>>>>> Suppose I have a list of strings, A. I want to compute the list (call >>>>> it B) of strings that are elements of A but doesn't match a regex. I >>>>> could use a for loop to do so. In a functional language, there is way >>>>> to do so without using the for loop.
>>>> Nonsense. For processing over each element, you have to loop over them, >>>> either with or without growing a call-stack at the same time.
>>>> FP languages can optimize away the stack-frame-growth (tail recursion) - but >>>> this isn't reducing complexity in any way.
>>>> So use a loop, either directly, or using a list-comprehension.
>>> What is a list-comprehension?
>>> I tried the following code. The list 'l' will be ['a','b','c'] rather >>> than ['b','c'], which is what I want. It seems 'remove' will disrupt >>> the iterator, right? I am wondering how to make the code correct.
>>> l ='a', 'a', 'b', 'c'] >>> for x in l: >>> if x ='a': >>> l.remove(x)
>>> print l
>> list comprehension seems to be what you want:
>> l =i for i in l if i != 'a']
> My problem comes from the context of using os.walk(). Please see the > description of the following webpage. Somehow I have to modify the > list inplace. I have already tried 'dirs =i for i in l if dirs !'a']'. But it seems that it doesn't "prune the search". So I need the > inplace modification of list.
> When topdown is True, the caller can modify the dirnames list in-place > (perhaps using del or slice assignment), and walk() will only recurse > into the subdirectories whose names remain in dirnames; this can be > used to prune the search, impose a specific order of visiting, or even > to inform walk() about directories the caller creates or renames > before it resumes walk() again. Modifying dirnames when topdown is > False is ineffective, because in bottom-up mode the directories in > dirnames are generated before dirpath itself is generated.
The context is quite important in this case. The os.walk() iterator gives you a tuple of three values, and one of them is a list. You do indeed want to modify that list, but you usually don't want to do it "in-place." I'll show you the in-place version first, then show you the slice approach.
If all you wanted to do was to remove one or two specific items from the list, then the remove method would be good. So in your example, you don' t need a loop. Just say: if 'a' in dirs: dirs.remove('a')
But if you have an expression you want to match each dir against, the list comprehension is the best answer. And the trick to stuffing that new list into the original list object is to use slicing on the left side. The [:] notation is a default slice that means the whole list.
dirs[:] = [ item for item in dirs if bool_expression_on_item ]
> I tried the following code. The list 'l' will be ['a','b','c'] rather > than ['b','c'], which is what I want. It seems 'remove' will disrupt the > iterator, right? I am wondering how to make the code correct.
> l = ['a', 'a', 'b', 'c'] > for x in l: > if x == 'a': > l.remove(x)
Oh lordy, it's Shlemiel the Painter's algorithm. Please don't do that for lists with more than a handful of items. Better still, please don't do that.
>> I tried the following code. The list 'l' will be ['a','b','c'] rather >> than ['b','c'], which is what I want. It seems 'remove' will disrupt the >> iterator, right? I am wondering how to make the code correct.
>> l = ['a', 'a', 'b', 'c'] >> for x in l: >> if x == 'a': >> l.remove(x)
> Oh lordy, it's Shlemiel the Painter's algorithm. Please don't do that for > lists with more than a handful of items. Better still, please don't do > that.
I understand what is Shlemiel the Painter's algorithm. But if the iterator can be intelligently adjusted in my code upon 'remove()', is my code Shlemiel the Painter's algorithm?
On Fri, Nov 6, 2009 at 5:57 PM, Dave Angel <da...@ieee.org> wrote:
> Peng Yu wrote:
>> On Fri, Nov 6, 2009 at 10:42 AM, Robert P. J. Day <rpj...@crashcourse.ca> >> wrote:
>>> On Fri, 6 Nov 2009, Peng Yu wrote:
>>>> On Fri, Nov 6, 2009 at 3:05 AM, Diez B. Roggisch <de...@nospam.web.de> >>>> wrote:
>>>>> Peng Yu schrieb:
>>>>>> Suppose I have a list of strings, A. I want to compute the list (call >>>>>> it B) of strings that are elements of A but doesn't match a regex. I >>>>>> could use a for loop to do so. In a functional language, there is way >>>>>> to do so without using the for loop.
>>>>> Nonsense. For processing over each element, you have to loop over them, >>>>> either with or without growing a call-stack at the same time.
>>>>> FP languages can optimize away the stack-frame-growth (tail recursion) >>>>> - but >>>>> this isn't reducing complexity in any way.
>>>>> So use a loop, either directly, or using a list-comprehension.
>>>> What is a list-comprehension?
>>>> I tried the following code. The list 'l' will be ['a','b','c'] rather >>>> than ['b','c'], which is what I want. It seems 'remove' will disrupt >>>> the iterator, right? I am wondering how to make the code correct.
>>>> l ='a', 'a', 'b', 'c'] >>>> for x in l: >>>> if x ='a': >>>> l.remove(x)
>>>> print l
>>> list comprehension seems to be what you want:
>>> l =i for i in l if i != 'a']
>> My problem comes from the context of using os.walk(). Please see the >> description of the following webpage. Somehow I have to modify the >> list inplace. I have already tried 'dirs =i for i in l if dirs !'a']'. But >> it seems that it doesn't "prune the search". So I need the >> inplace modification of list.
>> When topdown is True, the caller can modify the dirnames list in-place >> (perhaps using del or slice assignment), and walk() will only recurse >> into the subdirectories whose names remain in dirnames; this can be >> used to prune the search, impose a specific order of visiting, or even >> to inform walk() about directories the caller creates or renames >> before it resumes walk() again. Modifying dirnames when topdown is >> False is ineffective, because in bottom-up mode the directories in >> dirnames are generated before dirpath itself is generated.
> The context is quite important in this case. The os.walk() iterator gives > you a tuple of three values, and one of them is a list. You do indeed want > to modify that list, but you usually don't want to do it "in-place." I'll > show you the in-place version first, then show you the slice approach.
> If all you wanted to do was to remove one or two specific items from the > list, then the remove method would be good. So in your example, you don' t > need a loop. Just say: > if 'a' in dirs: > dirs.remove('a')
> But if you have an expression you want to match each dir against, the list > comprehension is the best answer. And the trick to stuffing that new list > into the original list object is to use slicing on the left side. The [:] > notation is a default slice that means the whole list.
> dirs[:] = [ item for item in dirs if bool_expression_on_item ]
I suggest to add this example to the document of os.walk() to make other users' life easier.
On Sat, 7 Nov 2009, Peng Yu wrote: > On Fri, Nov 6, 2009 at 5:57 PM, Dave Angel <da...@ieee.org> wrote: > > But if you have an expression you want to match each dir against, > > the list comprehension is the best answer. And the trick to > > stuffing that new list into the original list object is to use > > slicing on the left side. The [:] notation is a default slice > > that means the whole list.
> > dirs[:] = [ item for item in dirs if bool_expression_on_item ]
> I suggest to add this example to the document of os.walk() to make > other users' life easier.
huh? why do you need the slice notation on the left? why can't you just assign to "dirs" as opposed to "dirs[:]"? using the former seems to work just fine. is this some kind of python optimization or idiom?
rday --
======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA
>> On Fri, Nov 6, 2009 at 5:57 PM, Dave Angel <da...@ieee.org> wrote:
>> > But if you have an expression you want to match each dir against, >> > the list comprehension is the best answer. And the trick to >> > stuffing that new list into the original list object is to use >> > slicing on the left side. The [:] notation is a default slice >> > that means the whole list.
>> > dirs[:] = [ item for item in dirs if bool_expression_on_item ]
>> I suggest to add this example to the document of os.walk() to make >> other users' life easier.
> huh? why do you need the slice notation on the left? why can't you > just assign to "dirs" as opposed to "dirs[:]"? using the former seems > to work just fine. is this some kind of python optimization or idiom?
dirs = [...]
rebinds the name "dirs" while
dirs[:] = [...]
updates the contents of the list currently bound to the "dirs" name. The latter is necessary in the context of os.walk() because it yields a list of subdirectories, gives the user a chance to update it and than uses this potentially updated list to decide which subdirectories to descend into. A simplified example: