¿Si hay dos elementos máximos de una matriz?

Nov 25 2020

En este código, si el usuario escribe 2, dos veces y 1, dos veces. Luego hay dos elementos máximos y tanto Kinder como Twix deben imprimirse. Pero cómo ? Probablemente pueda hacer esto con el método if, pero esto hará que mi código sea aún más largo. ¿Alguna versión genial? ¿Puedo hacer esto con solo uno si?

a = [0, 0, 0,]
b = ["Kinder", "Twix", "Mars"]

while true 
  input = gets.chomp.to_i
  if input == 1
    a[0] += 1
  elsif input == 2
    a[1] += 1
  elsif input == 3 
    a[2] += 1
  elsif input == 0 
    break
  end 
end

index = a.index(a.max)
chocolate = b[index] if index
print a.max,chocolate
 

Respuestas

5 CarySwoveland Nov 25 2020 at 04:15

La pregunta realmente no tiene nada que ver con cómo ase construye la matriz .

def select_all_max(a, b)
  mx = a.max
  b.values_at(*a.each_index.select { |i| a[i] == mx })
end
b = ["Kinder", "Twix", "Mars"]
p select_all_max [0, 2, 1], b
["Twix"]

p select_all_max [2, 2, 1], b
["Kinder", "Twix"]

Consulte Array # values_at .


Alternativamente, esto podría hacerse en una sola pasada.

def select_all_max(a, b)
  b.values_at(
    *(1..a.size-1).each_with_object([0]) do |i,arr|
      case a[i] <=> arr.last
      when 0
        arr << i
      when 1
        arr = [i]
      end
    end
  )
end
p select_all_max [0, 2, 1], b
["Twix"]

p select_all_max [2, 2, 1], b
["Kinder", "Twix"]

p select_all_max [1, 1, 1], b
["Kinder", "Twix", "Mars"]
2 maxpleaner Nov 25 2020 at 04:06

Una forma sería la siguiente:

Primero, simplemente separe la recopilación de entrada del conteo, por lo que solo recopilaremos la entrada en este paso:

inputs = []
loop do
  input = gets.chomp.to_i
  break if input.zero?
  inputs << input 
end

Ahora podemos contar las entradas. Si tiene Ruby 2.7, simplemente puede hacerlo counts_by_input = inputs.tallypara obtener { "Twix" => 2, "Kinder" => 2 }. De lo contrario, mi enfoque preferido es usar group_by con transform_values :

counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }

Ahora, dado que vamos a extraer valores basados ​​en su recuento, queremos tener los recuentos como claves. Normalmente, podríamos invertir el hash, pero eso no funcionará en este caso porque solo nos dará un valor por clave, y necesitamos múltiples:

inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values

En su lugar, podemos usar otro group_by y transform_values(la razón por la que me gustan estos métodos es porque son muy versátiles ...):

inputs_by_count = counts_by_input.
  group_by { |input, count| count }.
  transform_values { |keyvals| keyvals.map(&:first) }
# => { 2 => ["Twix", "Kinder"] }

El transform_valuescódigo aquí es probablemente un poco confuso, pero una cosa importante a entender es que muchas veces, llamar a métodos Enumerables en hashes los convierte en [[key1, val1], [key2, val2]]matrices:

counts_by_input.group_by { |input, count| count }
# => { 2 => [["Twix", 2], ["Kinder", 2]] }

Es por eso que llamamos transform_values { |keyvals| keyvals.map(&:first) }después para obtener nuestro formato deseado{ 2 => ["Twix", "Kinder"] }

De todos modos, en este punto conseguir nuestro resultado es muy fácil:

inputs_by_count[inputs_by_count.keys.max]
# => ["Twix", "Kinder"]

Sé que probablemente todo esto parezca un poco loco, pero cuando se familiarice con los métodos de Enumerable podrá realizar este tipo de transformación de datos con bastante fluidez.

Tl; dr, dame el codez

inputs = []
loop do
  input = gets.chomp.to_i
  break if input.zero?
  inputs << input 
end

inputs_by_count = inputs.
  group_by(&:itself).
  transform_values(&:count).
  group_by { |keyvals, count| count }.
  transform_values { |keyvals| keyvals.map(&:first) }

top_count = inputs_by_count.keys.max
inputs_by_count[top_count]
# => ["Twix", "Kinder"]
2 hashrocket Nov 25 2020 at 04:09

Qué tal algo como esto:

maximum          = a.max # => 2
top_selling_bars = a.map.with_index { |e, i| b[i] if e == maximum }.compact # => ['Kinder', 'Twix']
p top_selling_bars # => ['Kinder', 'Twix']
1 Stefan Nov 25 2020 at 14:55

Si usted tiene

a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']

Puede calcular el valor máximo en a através de:

max = a.max #=> 2

y encuentre todos los elementos correspondientes a ese valor a través de:

b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]