Нарезка массива Python Как можно реализовать нарезку 2D-массива?

Мне интересно, как можно реализовать нарезку 2D-массива в Python?

Например,

arr является экземпляром самоопределяемого 2D-массива класса.

если я хочу включить синтаксис 2D-нарезки для этого объекта следующим образом:

arr[:,1:3] #retrieve the 1 and 2 column values of every row

or

arr[,:3] #retrieve the 1 and 2 column values of every row

Использование и синтаксис такие же, как у numpy.array. Но как реализовать такую ​​функциональность самостоятельно?

PS:

Что я имею в виду:

в первом случае часть [:,1:3] похожа на кортеж из двух частей

Однако для второго случая [,1:3] представляется довольно загадочным.


person xiaohan2012    schedule 19.04.2013    source источник
comment
Если вы реализуете класс, похожий на класс numpy, и хотите аналогичного поведения, почему бы просто не проверить их код?   -  person Bitwise    schedule 19.04.2013
comment
вы хотите создать свою собственную реализацию или хотите знать, как это сделать?   -  person Serdalis    schedule 19.04.2013


Ответы (4)


obj[,:3] недопустимый Python, поэтому он вызовет SyntaxError - Следовательно, у вас не может иметь этот синтаксис в исходном файле. (Это не удается, когда вы пытаетесь использовать его также в массиве numpy)

person mgilson    schedule 19.04.2013
comment
шутки Я полагаю, мы всегда могли надеяться, что они добавят этот синтаксис в серию python4.0 ... - person mgilson; 19.04.2013
comment
Ах, спасибо, что напомнили об ошибках! Думаю, теперь у меня есть ключ к разгадке! - person xiaohan2012; 19.04.2013
comment
Верно, obj[,:3] недопустимый синтаксис, но вы можете реализовать как obj[:,:3], так и obj[None,:3], поскольку это допустимый синтаксис .... - person NevilleDNZ; 12.05.2019

Если вы хотите узнать правила нарезки массива, может помочь изображение ниже:

введите описание изображения здесь

person wilbeibi    schedule 19.04.2013

Для доступа для чтения вам необходимо переопределить метод __getitem__:

class ArrayLike(object):
    def __init__(self):
        pass
    def __getitem__(self, arg):
        (rows,cols) = arg # unpack, assumes that we always pass in 2-arguments
        # TODO: parse/interpret the rows/cols parameters,
        # for single indices, they will be integers, for slices, they'll be slice objects
        # here's a dummy implementation as a placeholder 
        return numpy.eye(10)[rows, cols]

Один из сложных моментов состоит в том, что __getitem__ всегда использует только один аргумент (помимо self), когда вы помещаете элементы, разделенные несколькими запятыми, в квадратные скобки, вы фактически предоставляете один кортеж в качестве аргумента для вызова __getitem__; таким образом, необходимо распаковать этот кортеж (и, при желании, проверить, подходит ли длина кортежа) внутри функции.

Теперь, учитывая a = ArrayLike(), вы получите

  • a[2,3] означает rows=2, cols=3
  • a[:3,2] означает rows=slice(None, 3, None), cols=3

и так далее; чтобы решить как вы хотите использовать информацию о срезах для извлечения необходимых данных из вашего класса.

Чтобы сделать его более похожим на массив numpy, вы также захотите переопределить __setitem__, чтобы разрешить назначение элементам / фрагментам.

person Dave    schedule 03.01.2014

Вот хак, если это ваш собственный класс, и вы хотите передать строку.

Как переопределить оператор []?

class Array(object):

    def __init__(self, m, n):
        """Create junk demo array."""
        self.m = m
        self.n = n
        row = list(range(self.n))
        self.array = map(lambda x:row, range(self.m))

    def __getitem__(self, index_string):
        """Implement slicing/indexing."""

        row_index, _, col_index = index_string.partition(",")

        if row_index == '' or row_index==":":
            row_start = 0
            row_stop = self.m
        elif ':' in row_index:
            row_start, _, row_stop = row_index.partition(":")
            try:
                row_start = int(row_start)
                row_stop = int(row_stop)
            except ValueError:
                print "Bad Data"
        else:
            try:
                row_start = int(row_index)
                row_stop = int(row_index) + 1
            except ValueError:
                print "Bad Data"

        if col_index == '' or col_index == ":":
            col_start = 0
            col_stop = self.n
        elif ':' in col_index:
            col_start, _, col_stop = col_index.partition(":")
            try:
                col_start = int(col_start)
                col_stop = int(col_stop)
            except ValueError:
                print "Bad Data"
        else:
            try:
                col_start = int(col_index)
                col_stop = int(col_index) + 1
            except ValueError:
                print "Bad Data"

        return map(lambda x: self.array[x][col_start:col_stop],
                       range(row_start, row_stop))

    def __str__(self):
        return str(self.array)

    def __repr__(self):
        return str(self.array)


array = Array(4, 5)
print array
out: [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]

array[",1:3"]
out: [[1, 2], [1, 2], [1, 2], [1, 2]]

array[":,1:3"]
out: [[1, 2], [1, 2], [1, 2], [1, 2]]
person poof    schedule 19.04.2013