Wenn es zwei maximale Elemente eines Arrays gibt?
In diesem Code, wenn Benutzer 2 zweimal und 1 zweimal eingeben. Dann gibt es zwei maximale Elemente und sowohl Kinder als auch Twix sollten gedruckt werden. Aber wie ? Ich kann dies wahrscheinlich mit der if-Methode tun, aber dadurch wird mein Code noch länger. Irgendeine coole Version? Kann ich das mit nur einem machen, wenn?
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
Antworten
Die Frage hat wirklich nichts damit zu tun, wie das Array aufgebaut a
ist.
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"]
Siehe Array # values_at .
Dies könnte alternativ in einem einzigen Durchgang erfolgen.
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"]
Ein Weg wäre wie folgt:
Trennen Sie zunächst die Eingabeerfassung von der Zählung, damit wir in diesem Schritt nur die Eingabe erfassen:
inputs = []
loop do
input = gets.chomp.to_i
break if input.zero?
inputs << input
end
Jetzt können wir die Eingaben zusammenzählen. Wenn Sie Ruby 2.7 haben, können Sie einfach tun counts_by_input = inputs.tally
, um zu bekommen { "Twix" => 2, "Kinder" => 2 }
. Ansonsten ist es mein bevorzugter Ansatz, group_by mit transform_values zu verwenden :
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
Da wir nun Werte basierend auf ihrer Anzahl extrahieren, möchten wir die Anzahl als Schlüssel haben. Normalerweise können wir den Hash invertieren , aber das funktioniert in diesem Fall nicht, da wir nur einen Wert pro Schlüssel erhalten und mehrere benötigen:
inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values
Stattdessen können wir ein anderes verwenden group_by
und transform_values
(der Grund, warum ich diese Methoden mag, ist, dass sie sehr vielseitig sind ...):
inputs_by_count = counts_by_input.
group_by { |input, count| count }.
transform_values { |keyvals| keyvals.map(&:first) }
# => { 2 => ["Twix", "Kinder"] }
Der transform_values
Code hier ist wahrscheinlich etwas verwirrend, aber es ist wichtig zu verstehen, dass beim Aufrufen von Enumerable- Methoden für Hashes diese häufig in [[key1, val1], [key2, val2]]
Arrays konvertiert werden :
counts_by_input.group_by { |input, count| count }
# => { 2 => [["Twix", 2], ["Kinder", 2]] }
Deshalb rufen wir transform_values { |keyvals| keyvals.map(&:first) }
danach an, um unser gewünschtes Format zu erhalten{ 2 => ["Twix", "Kinder"] }
An diesem Punkt ist es jedenfalls sehr einfach, unser Ergebnis zu erhalten:
inputs_by_count[inputs_by_count.keys.max]
# => ["Twix", "Kinder"]
Ich weiß, dass dies wahrscheinlich alles ein wenig verrückt erscheint, aber wenn Sie sich mit Enumerable-Methoden vertraut machen, können Sie diese Art der Datentransformation ziemlich flüssig durchführen.
Tl; dr, gib mir den 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"]
Wie wäre es mit so etwas:
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']
Wenn Sie haben
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
Sie können den Maximalwert in a
via berechnen :
max = a.max #=> 2
und finden Sie alle Elemente, die diesem Wert entsprechen, über:
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]