Преобразовать вектор в целое число
Зная форму вектора многомерного массива, как мы можем преобразовать его в новый вектор одного измерения (сгладив многомерный массив)?
Например, учитывая следующий массив:
arr = [
[
[ nil, nil ],
[ nil, nil ],
[ nil, nil ]
],
[
[ nil, nil ],
[ nil, nil ],
[ nil, nil ]
]
]
arr[0][0][0] = "A"
arr[1][0][1] = "B"
arr # =>
[
[
[ "A", nil ],
[ nil, nil ],
[ nil, nil ]
],
[
[ nil, "B" ],
[ nil, nil ],
[ nil, nil ]
]
]
...где A
это происхождение и B
является местом назначения вектора. Можно написать:
shape = [2, 3, 2]
vector = [1, 0, 1]
Теперь предположим, что мы сплющены arr
Как мы могли перевести вектор? Другими словами, как перевести этот вектор 3 измерений в новый вектор 1 измерения?
Это особый случай, потому что источником вектора является также первая координата массива. Таким образом, мы можем найти результат с помощью:
arr.flatten.index("B") # => 7
Вот еще один пример с 2D-массивом:
arr = [
[ "A", nil ],
[ "B", nil ],
[ nil, nil ],
[ nil, nil ],
[ nil, nil ]
]
Мы можем написать это:
shape = [2, 5]
vector = [1, 0]
И вновь,
arr.flatten.index("B") # => 2
Но вот более сложный пример с отрицательным вектором:
arr = [
[ "B", nil ],
[ "A", nil ],
[ nil, nil ],
[ nil, nil ],
[ nil, nil ]
]
shape = [2, 5]
vector = [-1, 0]
Как можно написать следующий метод?
vector2index(shape, vector) # => -2
Пример (простой) с 1D-массивом:
arr = [ nil, "B", nil, nil, "A", nil, nil ]
shape = [7]
vector = [-3]
vector2index(shape, vector) # => -3
Есть ли простой способ выровнять вектор из массива любых размеров? Благодарю.
1 ответ
Прежде всего, если предположить, что первый элемент массива предназначен для оси X, второй - для оси Y, третий - для оси Z, во втором и третьем примере вы допустили ошибку. Третий пример должен быть
shape = [2,5]
vector = [0,-1]
vector2index(shape, vector) # => -2
И если первый элемент массива предназначен для оси Y, второй - для оси X, то 2-й и 3-й примеры верны, но первый пример неверен.
Если я правильно понимаю идею, нам нужно в первом примере умножить vector[1]
в shape[0]
, умножить vector[2]
в shape[0]*shape[1]
а затем рассчитать сумму из 3 элементов. Как правило, нам не нужно умножать 0-й элемент, и нам нужно умножить n-й элемент на shape[0]*shape[1]*...*shape[n-1]
,
Вы можете реализовать это следующим образом:
vector.each_with_index.map {
|v, i| i == 0? v: v * shape[0..i-1].inject(:*)
}.inject(:+)
Upd. После того, как вы обновили свой вопрос, он становится более понятным. Если вы хотите сохранить порядок индексации в Ruby, вы должны обратить оба массива в обратном порядке shape
а также vector
,
vector.reverse.each_with_index.map {
|v, i| i == 0? v: v * shape[0..i-1].reverse.inject(:*)
}.inject(:+)