配列の最大要素が2つある場合は?
このコードでは、ユーザーが2を2回、1を2回入力した場合。次に、最大2つの要素があり、KinderとTwixの両方を印刷する必要があります。しかし、どのように?私はおそらくifメソッドでこれを行うことができますが、これは私のコードをさらに長くします。クールなバージョンはありますか?1つだけでこれを行うことはできますか?
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
回答
この質問は、実際にはアレイのa
構築方法とは何の関係もありません。
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"]
Array#values_atを参照してください。
または、これを1回のパスで実行することもできます。
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"]
1つの方法は次のとおりです。
まず、入力収集とカウントを分離するだけなので、このステップで入力を収集します。
inputs = []
loop do
input = gets.chomp.to_i
break if input.zero?
inputs << input
end
これで、入力を集計できます。Ruby 2.7をお持ちの場合は、簡単counts_by_input = inputs.tally
に取得でき{ "Twix" => 2, "Kinder" => 2 }
ます。それ以外の場合、私の好ましいアプローチは、transform_valuesでgroup_byを使用することです。
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
ここで、カウントに基づいて値を抽出するので、カウントをキーとして使用します。通常、ハッシュを反転する場合がありますが、この場合は、キーごとに1つの値しか与えられず、複数の値が必要になるため、機能しません。
inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values
代わりに、私たちが使用することができます別のものを group_by
とtransform_values
(彼らは非常に汎用性だから、これらのメソッドのような理由私は...です):
inputs_by_count = counts_by_input.
group_by { |input, count| count }.
transform_values { |keyvals| keyvals.map(&:first) }
# => { 2 => ["Twix", "Kinder"] }
transform_values
ここのコードはおそらく少し紛らわしいですが、理解しておくべき重要なことの1つは、ハッシュでEnumerableメソッドを呼び出すと、それらが[[key1, val1], [key2, val2]]
配列に変換されることがよくあるということです。
counts_by_input.group_by { |input, count| count }
# => { 2 => [["Twix", 2], ["Kinder", 2]] }
そのtransform_values { |keyvals| keyvals.map(&:first) }
ため、後で呼び出して目的の形式を取得します{ 2 => ["Twix", "Kinder"] }
とにかく、この時点で結果を得るのは非常に簡単です。
inputs_by_count[inputs_by_count.keys.max]
# => ["Twix", "Kinder"]
私はこれがおそらく少し狂気に見えることを知っていますが、列挙可能なメソッドに慣れると、この種のデータ変換をかなり流暢に行うことができるようになります。
Tl; dr、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"]
このようなものはどうですか:
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']
あなたが持っている場合
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
次の方法で最大値を計算できますa
。
max = a.max #=> 2
そして、その値に対応するすべての要素を次の方法で見つけます。
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]