Reputation: 209
I want to get the slice of x[start1:stop1:step1 ]
and x[start2:stop2:step2]
in a single array.
Is there any syntax in Python like this:
x[start1:stop1:step1 + start2:stop2:step2]
In Matlab it is simply:
x(start1:step1:stop1 start2:step2:stop2)
update:
I see many answers suggest concatenation.
My intial goal is to do slice for higher dimension array, for example in 2D:
x[start1:stop1 + start2:stop2, start3:stop3 + start4:stop4]
Concatenation is okay. But it seems too complicated in high dimension.
Is there a way as simple as Matlab?
x(start1:stop1 start2:stop2, start3:stop3 start4:stop4 )
can we concatenate the array index, instead of the array itself?
Upvotes: 2
Views: 6711
Reputation: 9858
Your answer indicates you are using numpy
, so you can use r_
for this instead of constructing ranges.
test=np.random.random((20,20))
test[np.r_[1:8:2, 1:9:3], :][:, np.r_[1:9:3, 2:10:3]]
Indexing multidimensional arrays using sequences has been designed to work a bit differently from indexing using slices. e.g. test[[0, 1, 2], [3, 4, 5]]
will return an array containing test[0, 3], test[1, 4], test[2, 5]
. That's why test[D1, D2]
in your answer doesn't work.
If you want a slightly more convenient syntax you could make a class extending ndarray
with an altered method for handling indices:
class MultiArray(np.ndarray):
""" An array that can be indexed by multiple lists or arrays of indices
in the same way as by slices e.g.
m = MultiArray([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
m[[1, 2], [0, 3, 2]] # returns [[5, 8, 7], [9, 12, 11]]
Returns a standard array.
"""
def __new__(cls, input_array):
return np.asarray(input_array).view(cls)
def __getitem__(self, key):
r = np.array(self)
if type(key) is tuple:
for dimension, index in enumerate(key):
indices = [slice(None)] * len(key)
indices[dimension] = index
r = r[tuple(indices)]
return r
else:
return r[key]
print(MultiArray(test)[np.r_[1:8:2, 1:9:3], np.r_[1:9:3, 2:10:3]])
Upvotes: 2
Reputation: 209
Here is my solution:
D1=list(range(start1,stop1,step1))+list(range(start2,stop2,step2))
D2=list(range(start3,stop3,step3))+list(range(start4,stop4,step4))+"add more if you want"
x[D1,:][:,D2]
the effect is to select out the black regions in this Tartan pattern, from the whole cloth.
for example, test
is a 2D array.
D1
and D2
are some list of index in column and row. We wannt some cut
import numpy as np
test=np.random.random((20,20))
D1=list(range(1,8,2))+list(range(1,9,3))
D2=list(range(1,9,3))+list(range(2,10,3))
print(test[D1,:].shape)
print(test[:,D2].shape)
# test[D1,D2] will create error
output=test[D1,:][:,D2]
type(output)
output.shape
However, it is still unclear, why doesn't test[D1,D2]
work.
Upvotes: 0
Reputation: 365777
Concatenating the two lists, as in Jonas's answer, is the simplest solution, and usually the best.
If you're worried about making temporary lists, you can do something slightly more complicated, like:
[elem for i, elem in enumerate(x)
if i in range(start1, stop1, step1) or i in range(start2, stop2, step2)]
… or:
list(itertools.chain(itertools.islice(x, start1, stop1, step1),
itertools.islice(x, start2, stop2, step2)))
However, I'd expect either one to be a whole lot slower unless the two sublists are so huge that memory allocation time dominates everything, and of course they're a lot more complicated and less readable.
The only real advantage of either of these solutions is if you don't actually need the list, you can turn them into lazy iterators easily:
(elem for i, elem in enumerate(x)
if i in range(start1, stop1, step1) or i in range(start2, stop2, step2))
itertools.chain(itertools.islice(x, start1, stop1, step1),
itertools.islice(x, start2, stop2, step2))
(In fact, the second one is just the lazy equivalent of Jonas's answer: islice(x, start1, stop1, step1)
does the same thing as x[start1:stop1:step1]
, and chain(a, b)
does the same thing as a + b
.)
Upvotes: 0
Reputation: 483
Concatenate is a great way, or alternatively, you can join the two lists
part1 = x[start1:stop1:step1]
part2 = x[start2:stop2:step2]
mergedlist = part1 + part2
mergedlist = list(set(part1 + part2))
This will create a merged list, with a shallow copy of the items in the first list, followed by a shallow copy of the items in the second list.
If you want deep copy, you may use copy.deepcopy commands.
Upvotes: -2
Reputation: 743
This operation is also pretty easy in python. Once you've defined the list you can do your like this:
new_list = lst[start1:stop1:step1] + lst[start2:stop2:step2]
hope this helps.
Upvotes: 1
Reputation: 1573
You can concatenate two arrays (lists) like this: x[start1:stop1:step1] + x[start2:stop2:step2]
Upvotes: 2