Обработка Java-массива более двух измерений в виде списка

Я использую Groovy для написания DSL-обработки BASIC, и я хотел бы получить некоторую помощь в работе с многомерными (более чем 2) массивами.

Я имею дело с базовым кодом, как это:

100 LET X = A(1, 2, 3)

Легко обрабатывать одномерный случай - просто создайте замыкание (через MOP), которое возвращает элементы A, в то время как для двух измерений я могу сделать то же самое в форме

A(2, 3) == A.get(2)[3]

Но как мне работать с массивами неограниченных размеров?

Обновление: чтобы сделать это немного понятнее, вопрос заключается в том, как я могу динамически возвращать значения массива в контексте DSL? Интерпретатор сценариев видит A(1, 2, 3) как вызов функции, которую я могу перехватить с помощью MOP. Но как мне вернуть значение элемента массива в этом контексте?

2 ответа

Решение

В конце я решил проанализировать ввод и использовать его для создания замыкания через MOP:

    /* array references look like functions to Groovy so trap them */
    BinsicInterpreter.metaClass."$varName" = {Object[] arg ->
        def answer = "package binsic; $varName"
        arg.each { 
            answer = answer + "[$it]"
        }
        def something = shell.evaluate(answer)
        return something
    }

Так что, если бы мы имели:

100 LET X = A(10, 20, 3)

MOP перехватывает A(...) как вызов функции, а приведенный выше код дает мне A[10][20][3]

Если у вас n-мерный массив, смоделированный с помощью вложенных списков (не самый экономичный способ сделать это, но довольно простой в реализации), и вы хотите получить доступ к элементу по индексам [i_1, i_2, ... , i_n] ты можешь сделать:

def getElementAt(arr, ... indexes) {
    indexes.inject(arr) { a, ind -> a[ind] }
}

// A 2x2x3 array implemented with nested lists.
def arr = [[[1,1,1], [1,1,5]], [[1,1,1], [1,1,1]]]

// I want to get that 5!
assert getElementAt(arr, 0, 1, 2) == 5

// The line above is equivalent to:
assert arr[0][1][2] == 5

inject позволяет итерировать коллекцию и накапливать результат данной операции, начиная с начального значения. В этом случае мы итерируем индексы, которые мы хотим получить из массива, и начинаем итерацию со всего массива; каждая итерация затем возвращает подмассив с заданным индексом, который является значением, которое будет использоваться на следующей итерации. Если вы используете его с меньшим количеством индексов, чем ожидалось, он вернет список вместо целого числа, например getElementAt(arr, 0, 1) == [1, 1, 5],

Другие вопросы по тегам