在 [:index] 上使用动态索引进行列表切片
List slicing with dynamic index on [:index]
我需要使用负动态索引 ([:-index]) 对列表进行切片。这很容易,直到我意识到如果我的动态索引的值为 0,则不会返回任何项目,而不是返回整个列表。我如何以当索引为 0 时 returns 整个字符串的方式实现它?
我的代码很长很复杂,但基本上这个例子说明了问题:
arr='test text'
index=2
print arr[:-index]
>>'test te' #Entire string minus 2 from the right
index=1
print arr[:-index]
>>'test tex' #Entire string minus 1 from the right
index=0
print arr[:-index]
>>'' #I would like entire string minus 0 from the right
注意:我使用的是Python 2.7.
它有点脱离了切片符号的简洁性,但你可以做到
>>> arr[: len(arr) - 2]
'test te'
>>> arr[: len(arr) - 1]
'test tex'
>>> arr[: len(arr) - 0]
'test text'
您可以使用 None
而不是 0
来获取完整切片:
>>> arr = [1, 2, 3]
>>> index = 1
>>> arr[:-index if index else None]
[1, 2]
>>> index = 0
>>> arr[:-index if index else None]
[1, 2, 3]
我的测试:
import timeit
def jonrsharpe(seq, index):
return seq[:-index if index else None]
def Cyber(seq, index):
return seq[:len(arr) - index]
def shashank(seq, index):
return seq[:-index or None]
if __name__ == '__main__':
funcs = ('jonrsharpe', 'Cyber', 'shashank')
arr = range(1000)
setup = 'from __main__ import arr, {}'.format(', '.join(funcs))
for func in funcs:
print func
for x in (0, 10, 100, 1000):
print x,
print timeit.timeit('{}(arr, {})'.format(func, x), setup=setup)
结果:
jonrsharpe
0 2.9769377505
10 3.10071766781
100 2.83629358793
1000 0.252808797871
Cyber
0 3.11828875501
10 3.10177615276
100 2.82515282642
1000 0.283648679403
shashank
0 2.99515364824
10 3.11204965989
100 2.85491723351
1000 0.201558213116
另一个有趣的潜在解决方案。
>>> arr = [1, 2, 3]
>>> index = 0
>>> arr[:-index or None]
[1, 2, 3]
>>> index = 1
>>> arr[:-index or None]
[1, 2]
为了提高不可变序列类型(如字符串)的性能,您可以通过在切片操作 之前检查索引 的值来避免在索引为 0 的情况下完全切片序列。
这里有三个函数要测试性能:
def shashank1(seq, index):
return seq[:-index or None]
def shashank2(seq, index):
return index and seq[:-index] or seq
def shashank3(seq, index):
return seq[:-index] if index else seq
后两者在索引为 0 的情况下应该快,但在其他情况下可能会更慢(或更快)。
更新的基准代码: http://repl.it/oA5
注意:结果在很大程度上取决于 Python 实施。
由于在选择最佳正确答案之前我无法入睡,因此除了@jonrsharpe 提供的脚本之外,我还使用两个不同的脚本测试了每个答案的性能。
这是我用来比较三种不同解决方案性能的代码 profile
:
import profile
arr='test 123456789014'
def jonrsharpe(index):
global arr
for c in range(1,100000,1):
a=arr[:-index if index else None]
def Cyber(index):
global arr
for c in range(1,100000,1):
a=arr[:len(arr)-index]
def shashank(index):
global arr
for c in range(1,100000,1):
a=arr[:-index or None]
def testf():
for index in (0,3,6,9):
jonrsharpe(index)
Cyber(index)
shashank(index)
if __name__ == '__main__':
profile.run("testf()")
这是输出:
ncalls tottime percall cumtime percall filename:lineno(function)
799992 1.629 0.000 1.629 0.000 :0(len)
12 0.021 0.002 0.021 0.002 :0(range)
1 0.006 0.006 0.006 0.006 :0(setprofile)
1 0.000 0.000 4.390 4.390 <string>:1(<module>)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 4.396 4.396 profile:0(testf())
4 2.114 0.529 3.750 0.937 test.py:12(Cyber)
4 0.307 0.077 0.313 0.078 test.py:19(shashank)
1 0.000 0.000 4.390 4.390 test.py:26(testf)
4 0.319 0.080 0.328 0.082 test.py:5(jonrsharpe)
另一种方法:
import time
if __name__ == '__main__':
arr = '01234567890123456789012345678901234567890123456789'#range(1000)
for x in (0, 10, 20, 30,40,49):
print 'index=',x
start=time.clock()
for count in range(1000000):
a=arr[:-x if x else None]
print 'jonrsharpe=',round(time.clock()-start,4)
start=time.clock()
for count in range(1000000):
a=arr[:len(arr)-x]
print 'Cyber =',round(time.clock()-start,4)
start=time.clock()
for count in range(1000000):
a=arr[:-x or None]
print 'shashank =',round(time.clock()-start,4)
输出:
index= 0
jonrsharpe= 0.4918
Cyber = 0.5341
shashank = 0.4269
index= 10
jonrsharpe= 0.4617
Cyber = 0.5334
shashank = 0.4105
index= 20
jonrsharpe= 0.4271
Cyber = 0.4562
shashank = 0.3493
index= 30
jonrsharpe= 0.4217
Cyber = 0.4548
shashank = 0.3264
index= 40
jonrsharpe= 0.4713
Cyber = 0.8488
shashank = 0.6458
index= 49
jonrsharpe= 0.6159
Cyber = 0.5663
shashank = 0.4312
因为我将无数次使用这行代码,所以性能非常重要,@Shashank 的解决方案在大多数情况下都是赢家,即使只是一点点。
我需要使用负动态索引 ([:-index]) 对列表进行切片。这很容易,直到我意识到如果我的动态索引的值为 0,则不会返回任何项目,而不是返回整个列表。我如何以当索引为 0 时 returns 整个字符串的方式实现它? 我的代码很长很复杂,但基本上这个例子说明了问题:
arr='test text'
index=2
print arr[:-index]
>>'test te' #Entire string minus 2 from the right
index=1
print arr[:-index]
>>'test tex' #Entire string minus 1 from the right
index=0
print arr[:-index]
>>'' #I would like entire string minus 0 from the right
注意:我使用的是Python 2.7.
它有点脱离了切片符号的简洁性,但你可以做到
>>> arr[: len(arr) - 2]
'test te'
>>> arr[: len(arr) - 1]
'test tex'
>>> arr[: len(arr) - 0]
'test text'
您可以使用 None
而不是 0
来获取完整切片:
>>> arr = [1, 2, 3]
>>> index = 1
>>> arr[:-index if index else None]
[1, 2]
>>> index = 0
>>> arr[:-index if index else None]
[1, 2, 3]
我的测试:
import timeit
def jonrsharpe(seq, index):
return seq[:-index if index else None]
def Cyber(seq, index):
return seq[:len(arr) - index]
def shashank(seq, index):
return seq[:-index or None]
if __name__ == '__main__':
funcs = ('jonrsharpe', 'Cyber', 'shashank')
arr = range(1000)
setup = 'from __main__ import arr, {}'.format(', '.join(funcs))
for func in funcs:
print func
for x in (0, 10, 100, 1000):
print x,
print timeit.timeit('{}(arr, {})'.format(func, x), setup=setup)
结果:
jonrsharpe
0 2.9769377505
10 3.10071766781
100 2.83629358793
1000 0.252808797871
Cyber
0 3.11828875501
10 3.10177615276
100 2.82515282642
1000 0.283648679403
shashank
0 2.99515364824
10 3.11204965989
100 2.85491723351
1000 0.201558213116
另一个有趣的潜在解决方案。
>>> arr = [1, 2, 3]
>>> index = 0
>>> arr[:-index or None]
[1, 2, 3]
>>> index = 1
>>> arr[:-index or None]
[1, 2]
为了提高不可变序列类型(如字符串)的性能,您可以通过在切片操作 之前检查索引 的值来避免在索引为 0 的情况下完全切片序列。
这里有三个函数要测试性能:
def shashank1(seq, index):
return seq[:-index or None]
def shashank2(seq, index):
return index and seq[:-index] or seq
def shashank3(seq, index):
return seq[:-index] if index else seq
后两者在索引为 0 的情况下应该快,但在其他情况下可能会更慢(或更快)。
更新的基准代码: http://repl.it/oA5
注意:结果在很大程度上取决于 Python 实施。
由于在选择最佳正确答案之前我无法入睡,因此除了@jonrsharpe 提供的脚本之外,我还使用两个不同的脚本测试了每个答案的性能。
这是我用来比较三种不同解决方案性能的代码 profile
:
import profile
arr='test 123456789014'
def jonrsharpe(index):
global arr
for c in range(1,100000,1):
a=arr[:-index if index else None]
def Cyber(index):
global arr
for c in range(1,100000,1):
a=arr[:len(arr)-index]
def shashank(index):
global arr
for c in range(1,100000,1):
a=arr[:-index or None]
def testf():
for index in (0,3,6,9):
jonrsharpe(index)
Cyber(index)
shashank(index)
if __name__ == '__main__':
profile.run("testf()")
这是输出:
ncalls tottime percall cumtime percall filename:lineno(function)
799992 1.629 0.000 1.629 0.000 :0(len)
12 0.021 0.002 0.021 0.002 :0(range)
1 0.006 0.006 0.006 0.006 :0(setprofile)
1 0.000 0.000 4.390 4.390 <string>:1(<module>)
0 0.000 0.000 profile:0(profiler)
1 0.000 0.000 4.396 4.396 profile:0(testf())
4 2.114 0.529 3.750 0.937 test.py:12(Cyber)
4 0.307 0.077 0.313 0.078 test.py:19(shashank)
1 0.000 0.000 4.390 4.390 test.py:26(testf)
4 0.319 0.080 0.328 0.082 test.py:5(jonrsharpe)
另一种方法:
import time
if __name__ == '__main__':
arr = '01234567890123456789012345678901234567890123456789'#range(1000)
for x in (0, 10, 20, 30,40,49):
print 'index=',x
start=time.clock()
for count in range(1000000):
a=arr[:-x if x else None]
print 'jonrsharpe=',round(time.clock()-start,4)
start=time.clock()
for count in range(1000000):
a=arr[:len(arr)-x]
print 'Cyber =',round(time.clock()-start,4)
start=time.clock()
for count in range(1000000):
a=arr[:-x or None]
print 'shashank =',round(time.clock()-start,4)
输出:
index= 0
jonrsharpe= 0.4918
Cyber = 0.5341
shashank = 0.4269
index= 10
jonrsharpe= 0.4617
Cyber = 0.5334
shashank = 0.4105
index= 20
jonrsharpe= 0.4271
Cyber = 0.4562
shashank = 0.3493
index= 30
jonrsharpe= 0.4217
Cyber = 0.4548
shashank = 0.3264
index= 40
jonrsharpe= 0.4713
Cyber = 0.8488
shashank = 0.6458
index= 49
jonrsharpe= 0.6159
Cyber = 0.5663
shashank = 0.4312
因为我将无数次使用这行代码,所以性能非常重要,@Shashank 的解决方案在大多数情况下都是赢家,即使只是一点点。