You can use the same syntax as in R's c
, at the expense of an additional function call and a slight change in syntax, like this:
my_elements = slices(my_list, c[1, 3:5, 2:4, 9])
The trick is to use a c
object having a __getitem__
method. We can put anything we want between the brackets []
, and it will be passed to __getitem__
.
If we pass a mix of indices and slices, we'll get a tuple of integers and slice objects.
From there, our special __getitem__
will return a list of single indices that the slices function can use to extract the corresponding items from our list.
class C:
def __getitem__(self, idx_and_slices):
if not isinstance(idx_and_slices, tuple):
idx_and_slices = (idx_and_slices,)
indices = []
for x in idx_and_slices:
if isinstance(x, int):
indices.append(x)
elif isinstance(x, slice):
indices.extend(range(x.start, x.stop))
return indices
c = C()
def slices(lst, indices):
return [lst[i] for i in indices]
Usage:
my_list = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
my_elements = slices(my_list, c[1, 3:5, 2:4, 9])
print(my_elements)
# ['b', 'd', 'e', 'c', 'd', 'j']
More fun!
We could use an even "stranger", but shorter syntax, by also passing our list in the brackets, as in:
my_elements = d[my_list, 1, 3:5, 2:4, 9]
The __getitem__
method of d
will get a tuple with the list as first item, followed by the indices and slices, and will return the slice directly
class D:
def __getitem__(self, lst_idx_and_slices):
lst = lst_idx_and_slices[0]
idx_and_slices = lst_idx_and_slices[1:]
out = []
for x in idx_and_slices:
if isinstance(x, int):
out.append(lst[x])
elif isinstance(x, slice):
out.extend(lst[x.start:x.stop:x.step])
return out
d = D()
We would use it like this:
my_list = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
my_elements = d[my_list, 1, 3:5, 2:4, 9]
print(my_elements)
# ['b', 'd', 'e', 'c', 'd', 'j']