S'il y a deux éléments maximum d'un tableau?

Nov 25 2020

Dans ce code, si l'utilisateur tapez 2, deux fois et 1, deux fois. Ensuite, il y a deux éléments maximum et Kinder et Twix doivent être imprimés. Mais comment ? Je peux probablement le faire avec la méthode if mais cela rendra mon code encore plus long. Une version cool? Puis-je faire cela avec un seul 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
 

Réponses

5 CarySwoveland Nov 25 2020 at 04:15

La question n'a vraiment rien à voir avec la façon dont le tableau aest construit.

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"]

Voir Array # values_at .


Cela pourrait également être fait en un seul passage.

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

Une façon serait la suivante:

Tout d'abord, séparez simplement la collecte des entrées du comptage, nous allons donc simplement collecter les entrées dans cette étape:

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

Nous pouvons maintenant compter les entrées. Si vous avez Ruby 2.7, vous pouvez simplement le faire counts_by_input = inputs.tallypour obtenir { "Twix" => 2, "Kinder" => 2 }. Sinon, mon approche préférée est d'utiliser group_by avec transform_values :

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

Maintenant, puisque nous allons extraire des valeurs en fonction de leur nombre, nous voulons que les nombres soient des clés. Normalement, nous pourrions inverser le hachage, mais cela ne fonctionnera pas dans ce cas car cela ne nous donnera qu'une valeur par clé, et nous avons besoin de plusieurs:

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

Au lieu de cela, nous pouvons en utiliser un autre group_by et transform_values(la raison pour laquelle j'aime ces méthodes est qu'elles sont très polyvalentes ...):

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

Le transform_valuescode ici est probablement un peu déroutant, mais une chose importante à comprendre est que souvent, l'appel des méthodes Enumerable sur les hachages les convertit en [[key1, val1], [key2, val2]]tableaux:

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

C'est pourquoi nous appelons transform_values { |keyvals| keyvals.map(&:first) }ensuite pour obtenir le format souhaité{ 2 => ["Twix", "Kinder"] }

Quoi qu'il en soit, à ce stade, obtenir notre résultat est très simple:

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

Je sais que tout cela semble probablement un peu insensé, mais lorsque vous vous familiariserez avec les méthodes Enumerable, vous serez capable de faire ce type de transformation de données assez couramment.

Tl; dr, donne-moi le 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

Que diriez-vous quelque chose comme ça:

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 tu as

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

Vous pouvez calculer la valeur maximale avia:

max = a.max #=> 2

et retrouvez tous les éléments correspondant à cette valeur via:

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