Обработка 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]
,