Допустим, у меня есть следующие массивы:

arr1 = [
  ['a', 'b'],
  ['c', 'd'],
  ['e', 'f']
]

arr2 = [
  ['g', 'h'],
  ['i', 'k'],
  ['a', 'b']
]

Я хочу найти элементы в arr1, которых нет в arr2, и индекс элементов в arr1

Я могу сделать это со следующим, но это не очень эффективно и не очень красивое решение. В массивах также может быть много элементов, поэтому это не масштабируется. Есть лучший способ сделать это?

diff = arr1 - arr2

diff_with_index = diff.map { |x| { index: arr1.index(x), values: x } }

print diff_with_index
# [{:index=>1, :values=>["c", "d"]}, {:index=>2, :values=>["e", "f"]}]
0
New To Blue 1 Фев 2022 в 00:24
1
Не могли бы вы подробнее рассказать об «индексе элементов в arr1». Кажется немного запутанным, потому что что, если у arr2 есть "c", но нет "d", подходит ли вам это?
 – 
javierojeda
1 Фев 2022 в 00:32
Нет, это не тот случай. Чтобы он был действительным, он должен иметь оба элемента в одном и том же порядке. Поэтому мне нужно, чтобы он работал так же, как вычитание массива, но также получал индекс
 – 
New To Blue
1 Фев 2022 в 00:52
Просто потому, что это помеченные рельсы, можете ли вы объяснить, откуда берутся эти массивы и почему их сравнивают таким образом? Я считаю, что большинство вопросов о рельсах, связанных с наборами, имеют источник базы данных и обычно могут быть решены гораздо более эффективно в базе данных, чем в коде.
 – 
engineersmnky
1 Фев 2022 в 06:11

2 ответа

Вот один способ.

i1 = (0..arr1.size-1).to_a
  #=> [0, 1, 2]
h1 = arr1.zip(i1).to_h
  #=> {["a", "b"]=>0, ["c", "d"]=>1, ["e", "f"]=>2}
i1 - arr2.map { |a| h1[a] }
  #=> [1, 2]

Обратите внимание, что

arr2.map { |a| h1[a] }
  #=> [nil, nil, 0]
0
Cary Swoveland 1 Фев 2022 в 07:45

Когда вам нужно выполнить несколько проверок include?, наиболее эффективным способом является предварительное преобразование одного из списков в набор или хеш, чтобы у вас было время поиска O(1), поэтому что-то вроде этого:

require 'set'
arr2_set = Set.new(arr2)
arr1.each_index.select { |idx| !arr2_set.include?(arr1[idx]) }
2
max pleaner 1 Фев 2022 в 10:11
Я должен был прочитать ваш ответ, прежде чем публиковать свой, который я сейчас удалил. Обратите внимание, что наборы и хэши не совсем O(1), хотя это, безусловно, разумный способ выразить это.
 – 
Cary Swoveland
1 Фев 2022 в 01:38
Учитывая желаемый результат, filter_map.with_index, вероятно, лучше всего подходит.
 – 
engineersmnky
1 Фев 2022 в 06:03
О да, мой плохой, я не видел, что они тоже хотели недостающий элемент
 – 
max pleaner
1 Фев 2022 в 10:11