未分类

探究python切片原理,动手实现list切片

还能不动声色饮茶,踏碎这一场,盛世烟花

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- coding:utf-8 -*-

# 探究切片的原理
# 该代码的功能:用函数实现列表的切片,
def between(beg, end, mid):
return end > mid >= beg or end < mid <= beg

def get_slice(a, beg, end, delta = 1):
if delta == 0:
raise ValueError("slice step cannot be 0")
# 将负数转化成正数下标表示
if beg < 0:
beg += len(a)
if end < 0:
end += len(a)
# 如果转化完成之后依然不在合法范围内,则返回空列表
if beg < 0 and end < 0 or beg >= len(a) and end >= len(a):
print("begin都小于0 或 长度都越界")
return []

# 如果end-beg 与 delta 的方向不同,返回空列表
if(end - beg) * delta <= 0:
print("end - beg 与 delta 的方向不相同")
return []

# 对越界的部分裁剪,即beg或end超过的a的长度则返回a最后一个元素的下标即len(a) - 1
beg = max(0, min(beg, len(a) - 1))
end = max(-1, min(end, len(a)))
ans = []
i = beg
print("beg:%d, end:%d, delta:%d"%(beg, end, delta))
while between(beg, end, i):
ans.append(i)
i += delta
return ans



def test_getslice():
import random
a = list(range(10))
for i in range(10):
beg = random.randint(-15, 15)
end = random.randint(-15, 15)
delta = 0
while delta == 0:
delta = random.randint(-15, 15)
print("a:", a)
print("beg:%d,end:%d,delta:%d"%(beg, end, delta))
ans = get_slice(a, beg, end, delta)
print("get_slice(a, beg, end, delta):", ans)
print("a[beg:end:delta]:", a[beg:end:delta])
print(len(ans) == len(a[beg:end:delta]))
print("")


test_getslice()




"""
def between(beg, end, mid):
# 判断mid是否位于begin和end之间
return end > mid >= beg or end < mid <= beg


def get_slice(a, beg, end, delta=1):
# 数组切片get方式
if delta == 0: raise ValueError("slice step cannot be 0")
# 将负数下标转化一下
if beg < 0: beg += len(a)
if end < 0: end += len(a)
# 如果转化完成之后依然不在合法范围内,则返回空列表
if beg < 0 and end < 0 or beg >= len(a) and end >= len(a): return []
# 如果方向不同,则返回空列表
if (end - beg) * delta <= 0: return []
# 将越界的部分进行裁剪
beg = max(0, min(beg, len(a) - 1))
end = max(-1, min(end, len(a)))
ans = []
i = beg
while between(beg, end, i):
ans.append(a[i])
i += delta
return ans


def set_slice(a, li, beg, end, delta=1):
if delta == 0: raise ValueError("slice step cannot be 0")
if delta == 1:
# 如果delta==1,那么li的长度可以随意
if beg < 0: beg += len(a)
if end < 0: end += len(a)
beg = max(0, min(beg, len(a) - 1))
end = max(-1, min(end, len(a)))
for i in range(beg, end):
del a[beg]
for i in reversed(li):
a.insert(beg, i)
else:
# delta!=1,相当于替换
if len(get_slice(a, beg, end, delta)) != len(li): raise ValueError("array don't match")
if len(li) == 0: return
if beg < 0: beg += len(a)
if end < 0: end += len(a)
beg = max(0, min(beg, len(a) - 1))
# 用li中的全部元素逐一替换
for ind, value in enumerate(li):
a[ind * delta + beg] = value


def test_getSlice():
a = list(range(10))
import random
for i in range(10):
beg = random.randint(-15, 15)
end = random.randint(-15, 15)
delta = 0
while delta == 0: delta = random.randint(-15, 15)
print(len(get_slice(a, beg, end, delta)) == len(a[beg:end:delta]), beg, end, delta)


def test_setSlice():
import random
for i in range(10):
a = list(range(10))
beg = random.randint(-15, 15)
end = random.randint(-15, 15)
delta = 0
while delta == 0: delta = random.randint(-5, 5)
sz = len(a[beg:end:delta])
if delta == 1: sz = random.randint(0, 4)
li = [random.randint(0, 100) for i in range(sz)]
set_slice(a, li, beg, end, delta)
mine = a
a = list(range(10))
a[beg:end:delta] = li
print(a == mine)


test_setSlice()
"""

分享到