Using Python, I'm trying to read a list or strings backwards. When finding the item of interest, I want to print all of those items from that point to the end of the list. I can do this without recursion and it works fine, but I feel like there's a nic开发者_如何学JAVAer way to do this with recursion. :)
Example without recursion:
items = ['item1', 'item2', 'item3', 'item4', 'item5']
items_of_interest = []
items.reverse()
for item in items:
items_of_interest.append(item)
if item == 'item3':
break
else:
continue
items_of_interest.reverse()
print items_of_interest
['item3', 'item4', 'item5']
Update:
To add clarity to the question, the list is actually the output of a grep of a set of strings from a log file. The set of strings may be repeating and I only want the last set.
Recursion wouldn't make this simpler, it would make it more complicated.
for i, item in enumerate(reversed(items), 1):
if item == 'item3':
items_of_interest = items[-i:]
break
else:
# 'item3' wasn't found
seems to be the simplest efficient way to do this to me. You only have to iterate over the list from the end to 'item3'
, since reversed
returns an iterator.
Edit: if you don't mind iterating over the whole list to create a reversed version, you can use:
i = list(reversed(items)).index('item3')
items_of_interest = items[-i-1:]
which is even simpler. It raises an error if 'item3'
isn't in the list. I'm using list(reversed())
instead of [:]
then reverse()
because it's one iteration over the list instead of two.
Edit 2: Based on your comment to the other answer, my first version does what you want -- searches for the item from the end without iterating over the whole list. The version in the question has to iterate the list to reverse it, as does my second version.
A minimally modified, but more efficient, version of your original would be:
items_of_interest = []
for item in reversed(items):
items_of_interest.append(item)
if item == 'item3':
break
items_of_interest.reverse()
A recursive solution is not called for here. To the problem of finding the slice of a list from the last occurrence of a item to the end of the list, one approach is to define an auxiliary function
>>> def rindex(s, x):
... for i, y in enumerate(reversed(s)):
... if x == y:
... return -i-1
... raise ValueError
...
>>> items[rindex(items, "b"):]
['b', 'f']
The auxiliary function can be called rindex
because Python has a rindex
method to find the last occurrence of a substring in a string.
If you must do it recursively (perhaps it is homework) then think about it as in this pseudocode (not yet worked out completely)
def tail_from(list, x):
return tail_from_aux(list, x, [])
def tail_from_aux(list, element, accumulated):
if list is empty:
return []
elif list ends with element
return element::accumulated
else:
last = list[-1]
return tail_from_aux(list[:-1], element, last::accumulated)
But, this is memory-intensive, goes through the whole list (inefficient), and is not Pythonic. It may be appropriate for other languages, but not Python. Do not use.
Since your actual question refers to files, and log files at that, you may not be able to reduce this problem to an array search. Therefore, check out Read a file in reverse order using python, there are some interesting answers there as well as some links to follow.
Consider mixing tac
with awk
and grep
if you are able to as well.
精彩评论