Преобразовать вектор в целое число

Зная форму вектора многомерного массива, как мы можем преобразовать его в новый вектор одного измерения (сгладив многомерный массив)?

Например, учитывая следующий массив:

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(:+)
Другие вопросы по тегам