Jika ada dua elemen maksimum dari sebuah array?
Dalam kode ini jika pengguna mengetik 2, dua kali dan 1, dua kali. Lalu ada dua elemen maksimum dan Kinder dan Twix harus dicetak. Tapi bagaimana caranya ? Saya mungkin bisa melakukan ini dengan metode if tetapi ini akan membuat kode saya lebih lama. Ada versi yang keren? Bisakah saya melakukan ini hanya dengan satu jika?
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
Jawaban
Pertanyaannya sebenarnya tidak ada hubungannya dengan bagaimana array aitu dibangun.
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"]
Lihat Array # values_at .
Alternatifnya, ini bisa dilakukan dalam satu operan.
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"]
Salah satu caranya adalah sebagai berikut:
Pertama, pisahkan pengumpulan-masukan dari penghitungan, jadi kita hanya akan mengumpulkan masukan pada langkah ini:
inputs = []
loop do
input = gets.chomp.to_i
break if input.zero?
inputs << input
end
Sekarang kita bisa menghitung inputnya. Jika Anda memiliki Ruby 2.7, Anda dapat melakukannya counts_by_input = inputs.tallyuntuk mendapatkannya { "Twix" => 2, "Kinder" => 2 }. Jika tidak, pendekatan yang saya sukai adalah menggunakan group_by dengan transform_values :
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
Sekarang, karena kita akan mengekstrak nilai berdasarkan jumlah mereka, kita ingin menghitungnya sebagai kunci. Biasanya kita mungkin membalikkan hash, tetapi itu tidak akan berhasil dalam kasus ini karena itu hanya akan memberi kita satu nilai per kunci, dan kita membutuhkan beberapa:
inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values
Sebagai gantinya, kita dapat menggunakan yang lain group_by dan transform_values(alasan saya menyukai metode ini adalah karena mereka sangat serbaguna ...):
inputs_by_count = counts_by_input.
group_by { |input, count| count }.
transform_values { |keyvals| keyvals.map(&:first) }
# => { 2 => ["Twix", "Kinder"] }
The transform_valueskode di sini mungkin agak membingungkan, tapi satu hal yang penting untuk dipahami adalah bahwa sering kali, memanggil Enumerable metode pada hash bertobat mereka untuk [[key1, val1], [key2, val2]]array:
counts_by_input.group_by { |input, count| count }
# => { 2 => [["Twix", 2], ["Kinder", 2]] }
Itulah mengapa kami menelepon transform_values { |keyvals| keyvals.map(&:first) }setelah itu untuk mendapatkan format yang kami inginkan{ 2 => ["Twix", "Kinder"] }
Bagaimanapun, pada titik ini mendapatkan hasil kami sangat mudah:
inputs_by_count[inputs_by_count.keys.max]
# => ["Twix", "Kinder"]
Saya tahu ini mungkin semua tampak sedikit gila, tetapi ketika Anda terbiasa dengan metode Enumerable, Anda akan dapat melakukan transformasi data semacam ini dengan cukup lancar.
Tl; dr, beri aku kodez
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"]
Bagaimana dengan sesuatu yang seperti ini:
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']
Jika Anda memiliki
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
Anda dapat menghitung nilai maksimum amelalui:
max = a.max #=> 2
dan temukan semua elemen yang sesuai dengan nilai itu melalui:
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]