배열의 최대 요소가 두 개라면?

Nov 25 2020

이 코드에서 사용자가 2, 두 번 및 1을 입력하면 두 번. 그런 다음 두 개의 최대 요소가 있으며 Kinder와 Twix가 모두 인쇄되어야합니다. 하지만 어떻게? 나는 아마도 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
 

답변

5 CarySwoveland Nov 25 2020 at 04:15

질문은 실제로 배열 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"]
2 maxpleaner Nov 25 2020 at 04:06

한 가지 방법은 다음과 같습니다.

먼저 입력 수집과 계산을 분리하여이 단계에서 입력을 수집합니다.

inputs = []
loop do
  input = gets.chomp.to_i
  break if input.zero?
  inputs << input 
end

이제 입력을 집계 할 수 있습니다. 루비 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 }

이제 개수를 기준으로 값을 추출 할 것이기 때문에 개수를 키로 갖기를 원합니다. 일반적으로 해시를 반전 할 수 있지만이 경우에는 키당 하나의 값만 제공하고 여러 개가 필요하기 때문에이 경우에는 작동하지 않습니다.

inputs_by_count = counts_by_input.invert
# => { 2 => "Kinder" }
# This doesn't work, it removed one of the values

대신, 우리가 사용할 수있는 다른 group_bytransform_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; dr, 코드를 줘

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"]
2 hashrocket Nov 25 2020 at 04:09

다음과 같은 것은 어떻습니까?

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']
1 Stefan Nov 25 2020 at 14:55

당신이 가지고 있다면

a = [2, 2, 0,]
b = ['Kinder', 'Twix', 'Mars']

다음을 a통해 최대 값을 계산할 수 있습니다 .

max = a.max #=> 2

다음을 통해 해당 값에 해당하는 모든 요소를 ​​찾습니다.

b.select.with_index { |_, i| a[i] == max }
#=> ["Kinder", "Twix"]