Reputation: 3914
The following code gets the last present value from an ordered list of dated values:
def test_get_last_value(self):
dated_optional_values = [(datetime.datetime(2015, 2, 23), None),
(datetime.datetime(2015, 2, 24), 1.23),
(datetime.datetime(2015, 2, 25), None),
(datetime.datetime(2015, 2, 26), 2.34),
(datetime.datetime(2015, 2, 27), None),
]
present_values = [dated_optional_value[1] for dated_optional_value in dated_optional_values
if dated_optional_value[1] is not None]
last_present_value = present_values[-1]
print('last_present_value=', last_present_value)
I can easily write a loop which starts at the end of the list and iterates back until it finds a value.
Is there a more Pythonic way to accomplish that?
Upvotes: 2
Views: 3787
Reputation: 114569
It may be nice to factor the separate steps:
You want the second column (x[1]
)
def column(data, index): return [x[index] for x in data]
You want to filter out None
def notNone(data): return [x for x in data if x is not None]
You want the last element
def last(data): return data[-1]
Then your problem becomes
last_preset_value = last(notNone(column(data, 1)))
Upvotes: 1
Reputation: 142206
You can also generalise this to take the last n
non None
values - for instance, to take the last 2 non blanks:
from itertools import islice
candidates = (el[1] for el in reversed(dated_optional_values) if el[1] is not None)
last_n = list(islice(candidates, 2)) or []
Also, if you don't have a Sized
container, such as a list, and have some arbitrary iterable, you can use a collections.deque
with a fixed size, eg:
from collections import deque
candidates = (el[1] for el in dated_optional_values if el[1] is not None)
d = deque([], 2)
d.extendleft(candidates)
matches = list(d) or []
Both of these options return:
[2.34, 1.23]
Upvotes: 0
Reputation: 279325
next((dop[1] for dop in reversed(date_optional_values) if dop[1] is not None), None)
You can replace the final None
with whatever other value you prefer to return the case where every value is None
. Or omit that argument to throw an exception in the case where they're all None
.
Upvotes: 3
Reputation: 184280
Maybe:
last_present_value = next(x for x in reversed(dated_optional_values)
if x[1] is not None)
Upvotes: 3