如何获取列表的反向副本(在 .reverse 后链接方法时避免使用单独的语句)?
- 2024-12-27 08:46:00
- admin 原创
- 113
问题描述:
此代码失败:
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)
我收到一条异常信息AttributeError: 'NoneType' object has no attribute 'index'
。
我知道问题在于list.reverse()
返回None
,就地修改列表。我想.index
在反转列表上使用。有没有办法可以避免在索引列表之前使用单独的语句来反转列表?怎么做?
解决方案 1:
您可以使用切片来返回反转列表:
formation[::-1]
解决方案 2:
您可以使用reversed(formation)
返回 的反向迭代器formation
。调用时,formation.reverse()
它会对列表进行就地反转并返回 None。
编辑:
我知道你现在想做什么,在我看来,用列表理解来做这件事更容易:
def solution(formation):
return len([k for k in formation[formation.index(bCamel)+1:] if k == fCamel]) == 0
这基本上会查看第一个元素之后的所有元素bCamel
,并收集所有具有值的元素fCamel
。 如果该列表的长度 == 0,则您有一个解决方案。
以下是几个例子:
>>> 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
>>>
解决方案 3:
以GWW 的答案为基础,如果您希望此代码按原样工作,则只需执行list(reversed(formation))
。如果您确实希望能够使用formation.reverse()
,则必须将其子类化list
:
>>> class ReversableList(list):
... def reverse(self):
... return list(reversed(self))
...
>>> x = ReversableList([1,2,3])
>>> x.reverse()
[3, 2, 1]
当然,这是否可取是另一个问题。
解决方案 4:
list.reverse
就地反转。即:
>>> l = [1, 2, 3]
>>> l.reverse()
>>> l
[3, 2, 1]
请查阅 Python 文档,类似这样的内容都在那里列出,在本例中为可变序列类型。
s.reverse()
将s中的项反转到原位
您还可以尝试help
内置的:
>>> help(l.reverse)
Help on built-in function reverse:
reverse(...)
L.reverse() -- reverse *IN PLACE*
解决方案 5:
我刚刚遇到这个问题,想为来自 javascript 背景的新 Python 用户澄清一些事情。
在 javascript 中,a.reverse()
调用时原地反转并返回数组。
JavaScript的:
var a = [2, 3, 4]
console.log(a.reverse())
// outputs [4, 3, 2]
console.log(a)
// outputs [4, 3, 2]
在 python 中,a.reverse()
原地反转,但不返回数组。这就是让我感到困惑的地方。
在python中:
a = [2, 3, 4]
a.reverse()
print(a)
# outputs [4, 3, 2]
# can't do print(a.reverse())
解决方案 6:
以下变更将生效:
NumSet={1,2,3,4,5,6,7,8,9,10}
NumList = list(NumSet)
NumList.reverse()
print(NumList)
由于列表是可变类型,因此避免在初始赋值后使用赋值运算符。
将 = 运算符与方法一起使用..(例如 NumList = NumSet.reverse())将导致该方法用空白覆盖列表,从而有效地清除列表。这就是列表变为 NoneType 的原因。方法是函数,实际上没有自己的值,因此是空白。
解决方案 7:
针对 OP 中显示的问题,有多种方法。摘要:
使用不同的技术来获得列表的反转副本,以便可以就地使用此表达式
formation[::-1]
。实现此目的的两种主要方法是和list(reversed(formation))
(请参阅如何反转列表?)。
存在类似的解决方案来替代其他列表功能,例如:
# 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)
无论如何,还是咬紧牙关,使用单独的语句。
Simple is better than complex
;良好的 Python 风格通常会避免使用像 这样的长表达式((formation.index(bCamel) > (len(formation) - 1 - (formation.reverse()).index(fCamel))))
,因为很难理解其中的逻辑。请记住,由于我们仍在使用就地方法,因此原始方法formation
仍会被修改。这可能很有用,但通常会导致问题。(请不要在实际代码中使用它。)我们可以滥用条件表达式来使赋值作为副作用发生:
def solution(formation):
return formation.index(bCamel) > (
len(formation) - 1 - (formation.reverse() or formation).index(fCamel)
)
这个想法是,由于formation.reverse()
将返回None
,即假的,所以or
被迫不短路,并且在发生逆转后将评估为 formation
-作为副作用。
其他表达式可以具有相同的净效果,例如[formation, formation.reverse()][0]
。这个想法是编写一个包含调用但计算原始列表对象的表达式。我们可以在这里任意发挥创造力 - 但同样, 。请不要做这些事情。.reverse
`Simple is better than complex`
再次提醒,请记住这仍会修改原始列表,这可能会影响未来的计算。
重新设计逻辑以避免需要反转列表。代码尝试反转列表,在反转列表中搜索第一个匹配的索引,然后从中减去该结果
len(formation) - 1
- 这样做的总体效果是搜索最后一个匹配的索引。列表没有用于此的方法,但字符串有;而且碰巧的是,我们所有的元素都是单字符的字符串。我们可以通过使用字符串表示格式来更简单地解决问题:
def solution(formation):
return formation.index(bCamel) > formation.rindex(fCamel)
solution('F BF')
或者,我们可以用不同的方式思考这个问题:“fCamel
列表中第一个 后面的部分是否有bCamel
?” 公认的答案显示使用列表推导式迭代“列表中第一个 后面的部分bCamel
”,列出fCamel
那里的所有 s,并检查该列表是否为非空。但我们可以做得更简单:
# works with either the string or list input
def solution(formation):
return fCamel not in formation[formation.index(bCamel)+1:]
(有更聪明的方法来编写这个,比如 Stefan 使用迭代器的答案。)
此类解决方案特定于代码所解决的问题,并不回答一般问题。但是,通常可以在其他情况下找到类似的解决方案。
解决方案 8:
标题问题已经回答了,但你真正想要的是:
基本上,如果所有“F”都在第一个“B”的左侧,则此函数应返回 true
这与没有 'B' 后面跟着 'F' 是一样的。检查这一点的好方法是使用迭代器:
def solution(formation):
it = iter(formation)
return not (bCamel in it and fCamel in it)
一些优点:
与其他
formation.index(...)
解决方案不同,如果搜索到的值不存在,它也不会崩溃。仅占用 O(1) 额外空间(与对列表进行反向复制的解决方案不同)。
最多触及每个元素一次并尽快停止。甚至有 O(1) 时间最佳情况(即使有数百万个元素,如果列表以 开头,那么
['B', 'F',
它会立即停止)。
解决方案 9:
不是特别漂亮,但我在先前的答案中没有找到等效的答案。如果速度或内存成本较低(列表不是很长或操作重复次数不多),这相当直接,甚至更容易阅读。
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))))
解决方案 10:
您可以使用切片或reversed
函数。
例子:
a = [1, 2, 3, 4, 5]
b = a[::-1]
c = list(reversed(a))
assert b == c == [5, 4, 3, 2, 1]
这里b
和都c
代表的反转列表。注意:如果需要索引,a
请确保将reversed
函数的输出包装在中。由于给出了一个生成器。list
`reversed`
解决方案 11:
这并不能解决 F _ BF 模式问题,但它确实解决了使用 .reverse() 时python 不返回列表的问题。
我是这样解决这个问题的:
chars = ['a', '-', 'c']
chars2 = [] + chars
chars2.reverse()
totalChars = chars + chars2
totalChars 返回 a-cc-a,这正是我想要的,并且 chars2 是一个列表,而不是指向字符的指针。
解决方案 12:
不要这样做。
我在这里提出的方法肯定有效,原因如下。
list.reverse() 会反转列表,但不返回任何内容。期待它这样做会导致程序出现错误。
但是,从[list, list.reverse()][0]
技术上讲,这样做是可行的,因为list.reverse()
列表的第二项修改了list
列表的第一项中的元素。
正如@wjandrea 提到的,这太复杂了,最好的选择就是为list[::-1]
您提供列表的返回版本(不修改原始版本)
我不知道这对你是否有用,但这对我有用:
list = [1,2,3]
print([list, list.reverse()][0])
list.reverse() 返回 None 的原因是该函数没有返回任何内容。
使用您的代码:
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))