There are multiple approaches to the problem shown in the OP. A summary:
- Use a different technique that gives you a reversed copy of the list, so that this expression can be used in place. The two main ways to do this are
formation[::-1]
and list(reversed(formation))
(see How to reverse a list?).
Analogous solutions exist to replace other list functionality, for example:
# mylist.append(1)
# mylist.index(1)
(mylist + [1]).index(1) # note that the value is wrapped in another list
# mylist.extend(anotherlist)
# mylist.index(1)
(mylist + anotherlist).index(1)
# mylist.sort()
# mylist.index(1)
sorted(mylist).index(1)
Bite the bullet and use a separate statement anyway. Simple is better than complex
; good Python style often avoids long expressions like ((formation.index(bCamel) > (len(formation) - 1 - (formation.reverse()).index(fCamel))))
because it's hard to follow the logic. Keep in mind that since we are still using an in-place method, the original formation
is still modified. This can be useful, but it often causes problems.
(Please do not use this in real code.) We can abuse conditional expressions to make the assignment happen as a side effect:
def solution(formation):
return formation.index(bCamel) > (
len(formation) - 1 - (formation.reverse() or formation).index(fCamel)
)
The idea is that since formation.reverse()
will return None
, which is falsey, so or
is forced not to short-circuit, and will evaluate to formation
- after the reversal has occurred as a side effect.
Other expressions can have the same net effect, e.g. [formation, formation.reverse()][0]
. The idea is to write something that is an expression that includes the .reverse
call, but evaluates to the original list object. We can be arbitrarily creative here - but again, Simple is better than complex
. Please don't do these things.
Again, keep in mind that this will still modify the original list, which may impact on future calculations.
- Rework the logic to avoid the need to reverse the list. The code tries to reverse the list, search in the reversed list for the index of the first match, and then subtract that result from
len(formation) - 1
- the overall effect of this is to search for the index of the last match. Lists don't have a method for that, but strings do; and as it happens, all our elements are single-character strings. We could solve the problem more simply by representing the formation with a string:
def solution(formation):
return formation.index(bCamel) > formation.rindex(fCamel)
solution('F BF')
Alternately, we can conceive of the problem differently: "Is there a fCamel
in the part of the list that follows the first bCamel
?" The accepted answer shows using a list comprehension to iterate over "the part of the list that follows the first bCamel
", making a list of all the fCamel
s there, and checking whether that list is non-empty. But we can do it much more simply:
# works with either the string or list input
def solution(formation):
return fCamel not in formation[formation.index(bCamel)+1:]
(There are even more clever ways to write this, such as Stefan's answer using iterators.)
Solutions like this are specific to the problem solved by the code, and don't answer the question in general. However, it is often possible to find similar solutions in other contexts.