如果数组有两个最大元素?
If there's two maximum elements of an array?
在此代码中,如果用户键入 2,两次和 1,两次。然后有两个最大元素,应该打印 Kinder 和 Twix。但是怎么办?我可能可以用 if 方法做到这一点,但这会使我的代码更长。有好看的版本吗?我可以只用一个 if 吗?
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
一种方法如下:
首先,将输入收集与计数分开,因此我们将在这一步中收集输入:
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 }
。否则,我的首选方法是使用 group_by with transform_values:
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
现在,由于我们要根据计数提取值,因此我们希望将计数作为键。通常我们可能 invert 散列,但在这种情况下不起作用,因为它只会为每个键提供一个值,而我们需要多个:
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
代码可能有点令人困惑,但需要理解的一件重要事情是,通常,对散列调用 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"]
我知道这可能看起来有点疯狂,但是当您熟悉 Enumerable 方法后,您将能够非常流畅地进行这种数据转换。
Tl;博士,给我密码z
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
的构造方式无关。
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。
这也可以一次性完成。
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"]
如果你有
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
您可以通过以下方式计算 a
中的最大值:
max = a.max #=> 2
并通过以下方式找到与该值对应的所有元素:
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]
在此代码中,如果用户键入 2,两次和 1,两次。然后有两个最大元素,应该打印 Kinder 和 Twix。但是怎么办?我可能可以用 if 方法做到这一点,但这会使我的代码更长。有好看的版本吗?我可以只用一个 if 吗?
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
一种方法如下:
首先,将输入收集与计数分开,因此我们将在这一步中收集输入:
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 }
。否则,我的首选方法是使用 group_by with transform_values:
counts_by_input = inputs.group_by(&:itself).transform_values(&:count)
# => { "Twix" => 2, "Kinder" => 2 }
现在,由于我们要根据计数提取值,因此我们希望将计数作为键。通常我们可能 invert 散列,但在这种情况下不起作用,因为它只会为每个键提供一个值,而我们需要多个:
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
代码可能有点令人困惑,但需要理解的一件重要事情是,通常,对散列调用 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"]
我知道这可能看起来有点疯狂,但是当您熟悉 Enumerable 方法后,您将能够非常流畅地进行这种数据转换。
Tl;博士,给我密码z
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
的构造方式无关。
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。
这也可以一次性完成。
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"]
如果你有
a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']
您可以通过以下方式计算 a
中的最大值:
max = a.max #=> 2
并通过以下方式找到与该值对应的所有元素:
b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]