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 [(3,0), (4,0)]
One idea I had is: Get the cut-off key with
E = min (x [0] for x in s if (x [0] >= X) and (x [1] == -1) )
Then select elements with keys between the X
and E
:
R = [x for x in s if X <= x [0] < 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?
If you don't want duplicates, use a Set instead of a List . To convert a List to a Set you can use the following code: // list is some List of Strings Set<String> s = new HashSet<String>(list); If really necessary you can use the same construction to convert a Set back into a List .
To filter for unique values, click Data > Sort & Filter > Advanced. To remove duplicate values, click Data > Data Tools > Remove Duplicates. To highlight unique or duplicate values, use the Conditional Formatting command in the Style group on the Home tab.
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] != -1, (item for item in s if item[0] >= X)))
[(3, 0), (4, 0)]
Here, the generator expression, (item for item in s if item[0] >= 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 X
.
Then, we take values from that generator expression, only till we find a tuple whose second element is not equal to -1
, with itertools.takewhile
.
Here's a slightly hacky to implement takewhile
as part of a generator expression:
def stop(): raise StopIteration
result = (
stop() if item[1] == -1 else
item
for item in s
if item[0] >= X
)
Or with different phrasing:
def until(cond):
if cond: raise StopIteration
return True
result = (
item for item in s
if item[0] >= X
and until(item[1] == -1)
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With