This code fails:
fCamel = 'F'
bCamel = 'B'
gap = ' '
k开发者_开发百科 = ['F', ' ', 'B', 'F']
def solution(formation):
return ((formation.index(bCamel) > (len(formation) - 1 - (formation.reverse()).index(fCamel))))
solution(k)
I get an exception that says AttributeError: 'NoneType' object has no attribute 'index'
.
I know that the problem is that list.reverse()
returns None
, modifying the list in-place. I want to use .index
on the reversed list. Is there a way I can avoid using a separate statement to reverse the list before indexing into it? How?
You can use slicing to return the reversed list:
l[::-1]
You can use reversed(formation)
to return a reverse iterator of formation
. When you call formation.reverse()
it does an in place reversal of the list and returns None.
EDIT:
I see what you are trying to do now, in my opinion it's easier to just do this with a list comprehension:
def solution(formation):
return len([k for k in formation[formation.index(bCamel)+1:] if k == fCamel]) == 0
This basically looks at all the elements after the first bCamel
and collects all the elements that have the value fCamel
. If that list has a length == 0 you have a solution.
Here's a few examples:
>>> k = ['F','F','B','B','F']
>>> solution(k)
False
>>> k = ['F','F','B','B','B']
>>> solution(k)
True
>>> k = ['F','F','B','F','F','B','B']
>>> solution(k)
False
>>>
To build on GWW's answer, if you want this code to work as is you would just do list(reversed(formation))
. If you really want to be able to use formation.reverse()
instead, you would have to subclass list
:
>>> class ReversableList(list):
... def reverse(self):
... return list(reversed(self))
...
>>> x = ReversableList([1,2,3])
>>> x.reverse()
[3, 2, 1]
Whether or not this is advisable is another question of course.
list.reverse reverses inplace. That is:
>>> l = [1, 2, 3]
>>> l.reverse()
>>> l
[3, 2, 1]
Please consult the Python documentation, things like these are laid out there. You can also try the 'help' built-in:
help(l.reverse) Help on built-in function reverse:
reverse(...) L.reverse() -- reverse IN PLACE
I just came across this problem and wanted to clarify some things for users new to python coming from a javascript background.
In javascript, a.reverse() reverses in place and also returns the array when called.
Javascript:
var a = [2, 3 ,4]
console.log(a.reverse())
// outputs [4, 3, 2]
console.log(a)
// outputs [4, 3, 2]
In python, a.reverse() reverses in place, but does not return the array. This is what caused confusion for me.
In python:
a = [2, 3, 4]
a.reverse()
print(a)
# outputs [4, 3, 2]
# can't do print(a.reverse())
the following changes will be effective:
NumSet={1,2,3,4,5,6,7,8,9,10}
NumList = list(NumSet)
NumList.reverse()
print(NumList)
avoid using the assignment operator after the initial assignment as lists are mutable types.
Using = operator with a method..(eg NumList = NumSet.reverse()) will cause the method to overwrite list with a blank, thereby effectively clearing the list. That's why list becomes a NoneType. Methods are functions and doesn't actually have its own value, thus the blank.
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]
andlist(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 originalformation
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.
Not super beautiful, but I did not find the equivalent in the precedent answers. If the speed or memory costs are low (the list is not very long or the operation not repeated a huge amount of times), this is pretty straight forward and even easier to read.
import copy
fCamel = 'F'
bCamel = 'B'
gap = ' '
k = ['F', ' ', 'B', 'F']
def solution(formation):
rev_formation = copy.copy(formation)
rev_formation.reverse()
return ((formation.index(bCamel) > (len(formation) - 1 -
(rev_formation).index(fCamel))))
Cheers
This doesn't provide a solution to the F _ B F pattern problem, but it does address the issue of python not returning a list when you use .reverse().
This is how I got around it:
chars = ['a', '-', 'c']
chars2 = [] + chars
chars2.reverse()
totalChars = chars + chars2
totalChars returns a-cc-a, which is what I wanted, AND chars2 is a list, not a pointer to chars. Hope this helps.
I don't know if this works for you, but this works for me:
list = [1,2,3]
print([list, list.reverse()][0])
The reason list.reverse() returns None is because the function doesn't return anything.
Using your code:
fCamel = 'F'
bCamel = 'B'
gap = ' '
k = ['F', ' ', 'B', 'F']
def solution(formation):
return ((formation.index(bCamel) > (len(formation) - 1 - ([formation, formation.reverse()][0]).index(fCamel))))
print(solution(k))
Hope this works for you!
ps. Honestly, I have no idea why this works. I stumbled on it accidentally.
Title question is already answered, but for what you were really after:
Basically, this function should return true if all the 'F's are on the left hand side of the first 'B'
That's the same as there's no 'B' followed by an 'F'. Nice way to check this is with an iterator:
def solution(formation):
it = iter(formation)
return not (bCamel in it and fCamel in it)
Some advantages:
- Unlike every
formation.index(...)
solution it doesn't crash if the searched value isn't there. - Takes only O(1) extra space (unlike the solutions making a reversed copy of the list).
- Touches every element at most once and stops as soon as possible. Even has O(1) time best case (even with millions of elements, if the list starts with
['B', 'F',
then it stops right there).
精彩评论