Se ci sono due elementi massimi di un array?
In questo codice se l'utente digita 2, due volte e 1, due volte. Quindi ci sono due elementi massimi e devono essere stampati sia Kinder che Twix. Ma come ? Probabilmente posso farlo con il metodo if, ma questo renderà il mio codice ancora più lungo. Qualche versione interessante? Posso farlo con uno solo se?
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
Risposte
La domanda non ha davvero nulla a che fare con il modo in cui aviene costruito l'array .
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"]
Vedere Array # values_at .
Questo potrebbe in alternativa essere fatto in un unico passaggio.
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"]
Un modo potrebbe essere il seguente:
Innanzitutto, separa semplicemente la raccolta di input dal conteggio, quindi raccoglieremo solo input in questo passaggio:
inputs = []
loop do
input = gets.chomp.to_i
break if input.zero?
inputs << input
end
Ora possiamo calcolare gli input. Se hai Ruby 2.7 puoi semplicemente fare counts_by_input = inputs.tallyper ottenere { "Twix" => 2, "Kinder" => 2 }. Altrimenti, il mio approccio preferito è usare group_by con transform_values :
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
Ora, poiché estrarremo i valori in base al loro conteggio, vogliamo che i conteggi siano chiavi. Normalmente potremmo invertire l'hash, ma in questo caso non funzionerà perché ci darà solo un valore per chiave e abbiamo bisogno di più:
inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values
Invece, possiamo usarne un altro group_by e transform_values(il motivo per cui mi piacciono questi metodi è perché sono molto versatili ...):
inputs_by_count = counts_by_input.
group_by { |input, count| count }.
transform_values { |keyvals| keyvals.map(&:first) }
# => { 2 => ["Twix", "Kinder"] }
Il transform_valuescodice qui è probabilmente un po 'confuso, ma una cosa importante da capire è che spesso, chiamando i metodi Enumerable sugli hash, li converte in [[key1, val1], [key2, val2]]array:
counts_by_input.group_by { |input, count| count }
# => { 2 => [["Twix", 2], ["Kinder", 2]] }
Ecco perché chiamiamo in transform_values { |keyvals| keyvals.map(&:first) }seguito per ottenere il formato desiderato{ 2 => ["Twix", "Kinder"] }
Comunque a questo punto ottenere il nostro risultato è semplicissimo:
inputs_by_count[inputs_by_count.keys.max]
# => ["Twix", "Kinder"]
So che probabilmente tutto questo sembra un po 'folle, ma quando acquisirai familiarità con i metodi Enumerable sarai in grado di eseguire questo tipo di trasformazione dei dati abbastanza fluentemente.
Tl; dr, dammi il 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"]
Che ne dici di qualcosa del genere:
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']
Se hai
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
Puoi calcolare il valore massimo in avia:
max = a.max #=> 2
e trova tutti gli elementi corrispondenti a quel valore tramite:
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]