working - wordpress top level menu item not clickable
Stopping list selection? (6)
Imagine that I have an order list of tuples:
s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)]
Given a parameter
X, I want to select all the tuples that have a first element equal or greater than
X up to but not including the first tuple that has -1 as the second element.
For example, if
X = 3, I want to select the list
One idea I had is: Get the cut-off key with
E = min (x  for x in s if (x  >= X) and (x  == -1) )
Then select elements with keys between the
R = [x for x in s if X <= x  < E]
That gives me what I want in R, but it seems really inefficient, involving two table scans. I could do it in a for loop, discarding tuples with keys too small, and break when I hit the first blocking tuple. But for runs like a dog compared to list selection.
Is there a super-efficient, python-esque (2.7) way of doing this?
itertools.takewhile works well if you want a new list. To modify the original list in-place you could do:
>>> L = ['pin 2.3','vlo 5.4', '2 packages installed', 'bla-bla'] >>> for i, v in enumerate(L): ... if "packages installed" in v: ... del L[i:] ... break ... >>> L ['pin 2.3', 'vlo 5.4']
Because the syntax of
dropwhile() is not the clearest, here are the actual examples of your question:
>>> [i for i in itertools.takewhile(lambda x: x*x<30, range(10))] [0, 1, 2, 3, 4, 5] >>> [i for i in itertools.dropwhile(lambda x: x*x<30, range(10))] [6, 7, 8, 9]
Know that the author of itertools has questioned whether to deprecate these functions.
li1 = ['pin 2.3','vlo 5.4', 'lu 1.3', '3 packages installed', '', 'bla'] out1 =  for x in li1: if "packages installed" in x: break out1.append(x) print(out1) # ['pin 2.3', 'vlo 5.4', 'lu 1.3']
Edit: It seems like I'm a little bit late.
You can simply filter the tuples from the list as a generator expression and then you can stop taking the values from the generator expression when you get the first tuple whose second element is
-1, like this
>>> s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)] >>> from itertools import takewhile >>> X = 3 >>> list(takewhile(lambda x: x != -1, (item for item in s if item >= X))) [(3, 0), (4, 0)]
Here, the generator expression,
(item for item in s if item >= X) will give values one-by-one, on demand, (they are not generated all at once, so we save memory here) which are greater than or equal to
Then, we take values from that generator expression, only till we find a tuple whose second element is not equal to
Using while in list comprehension or generator expressions
The various functions in
takewhile() comes to mind) can help.
python: filter a list of strings based on a string name
You can use
itertools.takewhile, which takes items from the list until the given condition is not passed:
from itertools import takewhile l12 = ['pin 2.3','vlo 5.4', '2 packages installed', 'bla', 'bla'] li1 = ['pin 2.3','vlo 5.4', 'lu 1.3', '3 packages installed', '', 'bla'] r12 = takewhile(lambda x: "packages installed" not in x, l12) ri1 = takewhile(lambda x: "packages installed" not in x, li1) print(list(r12)) # ['pin 2.3', 'vlo 5.4'] print(list(ri1)) # ['pin 2.3', 'vlo 5.4', 'lu 1.3']