forked from UWPCE-PythonCert/IntroPython-2017
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathslice_sparse.py
More file actions
139 lines (125 loc) · 4.96 KB
/
Copy pathslice_sparse.py
File metadata and controls
139 lines (125 loc) · 4.96 KB
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
"""
example of emulating a sequence using slices
"""
class SparseArray(object):
def __init__(self, my_array=()):
self.length = len(my_array)
self.sparse_array = self._convert_to_sparse(my_array)
def _convert_to_sparse(self, my_array):
sparse_array = {}
for index, number in enumerate(my_array):
if number:
sparse_array[index] = number
return sparse_array
def __len__(self):
return self.length
def __str__(self):
msg = ['SparseArray: [']
for i in range(self.length):
msg.append("{} ".format(self[i]))
msg.append(']')
return "".join(msg)
def __getitem__(self, index):
# this version supports slicing -- far more complicated
mini_array = []
if isinstance(index, slice):
start, stop, step = index.indices(len(self))
if step is None:
step = 1
key = start
mini_array = []
while key < stop:
mini_array.append(self[key])
key += step
return mini_array
else:
# makes it an int, even if it's some other
# type that supports being used as an index
index = index.__index__()
return self._get_single_value(index)
def _get_single_value(self, key):
if key >= self.length:
raise IndexError('array index out of range')
else:
return self.sparse_array.get(key, 0)
def __setitem__(self, index, value):
if isinstance(index, slice):
start, stop, step = index.indices(len(self))
if step is None:
step = 1
key = start
new_values = []
new_keys = []
for each in value:
if key < stop:
self[key] = each
else:
# now instead of replacing values, we need to add (a) value(s) in the center,
# and move stuff over, probably want to collect all of the changes,
# and then make a new dictionary
new_values.append(each)
new_keys.append(key)
key += step
if new_keys:
self._add_in_slice(new_keys, new_values)
else:
index = index.__index__()
self._set_single_value(index, value)
def _set_single_value(self, key, value):
if key > self.length:
raise IndexError('array assignment index out of range')
if value != 0:
self.sparse_array[key] = value
else:
# if the value is being set to zero, we probably need to
# remove a key from our dictionary.
self.sparse_array.pop(key, None)
def _add_in_slice(self, new_keys, new_values):
# sometimes we need to add in extra values
# any existing values
# greater than the last key of the new data
# will be increased by how many
new_dict = {}
slice_length = len(new_keys)
for k, v in self.sparse_array.items():
if k >= new_keys[-1]:
# print('change keys')
# if greater than slice, change key
new_dict[k + slice_length] = v
elif k in new_keys:
# if this is a key we are changing, change it,
# unless we are changing to a zero...
new_value = values[new_keys.index(k)]
if new_value != 0:
new_dict[k] = new_value
else:
new_dict[k] = v
# what if our new key was not previously in the dictionary?
# stick it in now
for k in new_keys:
if k not in new_dict.keys():
new_dict[k] = new_values[new_keys.index(k)]
# note we don't want to do update, since we need to make sure we are
# getting rid of the old keys, when we moved the value to a new key
self.sparse_array = new_dict
# now we need to increase the length by the amount we increased our array by
self.length += slice_length
def __delitem__(self, key):
# we probably need to move the keys if we are not deleting the last
# number, use pop in case it was a zero
if key == self.length - 1:
self.sparse_array.pop(key, None)
else:
# since we need to adjust all of the keys after the one we are
# deleting, probably most efficient to create a new dictionary
new_dict = {}
for k, v in self.sparse_array.items():
if k >= key:
new_dict[k - 1] = v
else:
new_dict[k] = v
# note we don't want to do update, since we need to make sure we are
# getting rid of the old keys, when we moved the value to a new key
self.sparse_array = new_dict
# length is now one shorter
self.length -= 1