Найдите индекс несоответствия в массиве

У меня есть массив, который должен содержать одно и то же значение, и если есть несоответствия, я хочу получить индекс этих несоответствий.

Пример:

[1,1,1,1,3,1,1,1,2,1,1,1]

Выход:

[4, 8]

Как лучше всего это сделать в Ruby/Rails?

Знаете ли вы заранее, что ищете в массиве элементы, отличные от 1? Или вам нужно сначала выяснить, какой элемент является наиболее распространенным, прежде чем искать несоответствия?

spickermann 07.03.2024 15:54

Подозреваю, что #tally и #group_by будут полезны.

Chris 07.03.2024 16:08

Нет, не могу этого предположить. Я просто использовал 1 в качестве примера.

Jeremy Thomas 07.03.2024 16:14

А что, если у тебя есть [1,1,1,2,2,2,3,4,5]? т. е. в данном случае наиболее распространенным значением являются и 1, и 2.

dawg 07.03.2024 16:56

Что вы будете делать с индексами «несовпадений»?

Cary Swoveland 08.03.2024 03:50
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
0
5
114
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

что-то вроде:

def find_non_matching_indexes(array, value)
  # Use `each_with_index` to iterate through the array with indexes
  array.each_with_index.select do |element, index|
    # Select elements where the value is not the given value
    element != value
  end.map(&:last) # Extract only the indexes from the selected elements
end

Проблема в том, что я не знаю значения заранее. Сначала нам нужно определить основное значение, присутствующее в массиве.

Jeremy Thomas 07.03.2024 16:16
def find_mismatch_indices(arr, main_value)
  arr.each_index.select { |i| arr[i] != main_value }
end

my_array = [1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1]
main_value = my_array.tally.max_by { |_, count| count }.first
result = find_mismatch_indices(my_array, main_value)

puts "Indices of mismatches: #{result.inspect}"

Выход

Indices of mismatches: [4, 8]
Ответ принят как подходящий

Вы можете получить наиболее распространенный элемент с помощью tally и max_by:

arr = [1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1]

most_common = arr.tally.max_by(&:last).first
#=> 1

tally возвращает хэш, содержащий количество вхождений каждого элемента ({1=>10, 3=>1, 2=>1}), max_by(&:last) возвращает пару с наибольшим количеством вхождений, а first возвращает значение этого элемента. (при условии, что всегда есть один наиболее распространенный элемент)

Чтобы получить индексы, вы можете использовать filter_map:

arr.each_with_index.filter_map { |e, i| i if e != most_common }
#=> [4, 8]

each_with_index возвращает каждому элементу соответствующий индекс. filter_map выбирает правдивые результаты из блока, который возвращает индекс элемента, если элемент не равен 1. (и nil в противном случае, который отбрасывается)

...или arr.each_index.reject { |i| arr[i] == most_common }.

Cary Swoveland 08.03.2024 04:18

@CarySwoveland это еще короче, но мне почему-то не нравится запрашивать массив, который я уже перебираю.

Stefan 08.03.2024 12:55

У всех нас есть свои слабости. Не могу заставить себя использовать compact.

Cary Swoveland 08.03.2024 19:20

Нам нужно преобразовать данные, чтобы определить, где и как часто встречаются элементы.

>  a = [1,1,1,1,3,1,1,1,2,1,1,1]
=> [1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, 1]
> b = a.each_with_index.sort_by(&:first).group_by(&:first).transform_values { _1.map(&:last) }
=> {1=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 2=>[10], 3=>[11]}

Затем нам просто нужно исключить все элементы, кроме самого распространенного, и извлечь индексы.

> b.sort_by(&:length)[..-2].map { _1[1][0] }.sort
=> [4, 8]

Я получаю разные результаты при запуске этого кода.

Stefan 07.03.2024 16:37

Мы могли бы немного очистить первоначальное формирование хеша, используя a.each_with_index.group_by(&:shift).transform_values(&:flatt‌​en)

engineersmnky 07.03.2024 21:35

@ Стефан, какие результаты ты получаешь? Я скопировал и вставил прямо из IRB.

Chris 07.03.2024 22:57

@Крис, я получаю {1=>[11, 1, 2, 3, 10, 0, 5, 6, 7, 9], 2=>[8], 3=>[4]} за первое выражение и [8, 11] за второе.

Stefan 08.03.2024 08:20

Просто еще одна версия:

[1,1,1,1,3,1,1,1,2,1,1,1]
   .each_with_object(Hash.new { |hash, key| hash[key] = [] })
   .with_index { |(e, hash), i| hash[e] << i } # collect elements with their index
   .values                                     # only return the indexes
   .sort_by(&:size)                            # sort indexes arrays by size
   .slice(..-2)                                # return all but the longest
   .flatten                                    # flatten
#=> [4, 8]

Альтернативно .values.then {|a| a.delete(a.max_by(&:size)) && a.flatten } или производные от, например. (a - [a.max_by(&:size)]).flatten, a.flatten.difference(a.max_by(&:size)) и т. д.

engineersmnky 07.03.2024 20:58

Если вы используете tally и max_by, вы учитываете только один наиболее распространенный вариант.

Предположим, у вас есть эти массивы:

arr1=[1,1,1,1,3,1,1,1,2,1,1,1]  # should be [4,8]
arr2=[1,1,1,3,3,3,4,4,4,2] # should be [9]?
arr3=[1,1,1,1,1,1] # should be []?
arr4=[1,1,1,2,2,2,3,3,3] # should be []?

Затем рассмотрите этот подход, который позволяет использовать более одного значения или отсутствие значения как «наиболее распространенного»:

def index_of_minority(arr)
    tal=arr.tally.sort_by(&:last).reverse
    most_common,rest=tal.partition{|e,cnt| cnt==tal[0][1]}.map{|sa| sa.to_h}
    arr.each_with_index.select{|e,i| rest.key?(e) }.map(&:last)
end    

Затем с этими массивами:

[arr1,arr2,arr3,arr4].each{|arr| p index_of_minority(arr) }
[4, 8]
[9]
[]
[]

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