Как срез в виде строки преобразовать в объект, который можно использовать как срез массива

В цикле получаю список срезов

qw = ['0:10, 0:20', '10:20, 20:40', '20:30, 40:60']

То есть каждый срез представлен в виде строки. После этого пытаюсь применить этот срез к массиву

im = [[[0,0,0], [0,0,0]], [[0,0,0], [0,0,0]], [[0,0,0], [0,0,0]]...]

Но т.к. это строка, то применить не получиться. Пыталась сделать так, но поняла что приду опять к строке

ind = i.split(',')
ind = [int(i) for i in ind]
int_ind = ','.join(ind)

Необходимо получить объекты массива по заданным срезам.

for i in qw:
  print(img[i])

где i должен быть работающим срезом, то есть

img[0:10, 0:20]

Ответы (1 шт):

Автор решения: insolor
  1. Нужно вытащить все числа из строк (это можно сделать с помощью регулярных выражений), преобразовать их в целые

  2. Сформировать объект среза. Тут смысл в том, что срез вида img[a:b] - это объект типа slice, когда два среза через запятую - это кортеж (tuple) из двух slice. Т.е.:

    • img[0:10] это то же самое что img[slice(0, 10)] (или img[slice(0, 10, None)], но пустой шаг слайса можно не указывать)
    • img[0:10, 0:20] - img[(slice(0, 10), slice(0, 20))].

    В этом можно убедиться на таком коде:

    class Test:
        def __getitem__(self, x):
            return x
    
    
    print(Test()[0:10])  # slice(0, 10, None)
    print(Test()[0:10, 0:20])  # (slice(0, 10, None), slice(0, 20, None))
    

Таким образом, нужно сформировать объект вида (slice(0, 10), slice(0, 20)), подставить туда числа с первого шага.

import numpy as np
import re


def convert_to_slice(s: str):
    a, b, c, d = map(int, re.findall(r"\d+", s))  # Вытаскиваем все числа из строки (считаем, что их всегда 4 штуки)
    return (slice(a, b), slice(c, d))  # Формируем объект нужного вида


img = np.array([[[0,0,0], [1,1,1]], [[2,2,2], [3,3,3]], [[4,4,4], [5,5,5]]])

# Результат должен получиться одинаковым
print(img[0:1, 0:2])
print(img[convert_to_slice('0:1, 0:2')])

Результат:

[[[0 0 0]
  [1 1 1]]]
[[[0 0 0]
  [1 1 1]]]

Если смотреть в контексте вашего предыдущего вопроса, то вместо формирования строк-срезов можно в цикле сразу формировать список из объектов-срезов:

def convert_to_slice(a, b, c, d):
    return (slice(a, b), slice(c, d))


qw = []

for i in range(5):
    qw.append(convert_to_slice(
        i * y_shift, i * y_shift + y_size,
        i * x_shift, i * x_shift + x_size,
    ))
→ Ссылка