首页 > 解决方案 > 如何简化此类方法?

问题描述

我有一个班级,有 50 个随机分数的随机人,存储在哈希数组中:

def initialize
    # adding fake names and numbers
    require 'faker'
    @people = []
    (1..50).each do
      @people << { name: Faker::Name.first_name, score: Faker::Number.between(1, 1000).to_i }
    end
end

特别是该top方法(如下)将返回字符串中排名前 N 的人及其分数。作为 ruby​​ 的新人,我认为可能有一种方法可以让这变得更简单。这是方法:

def top(number=10)
    top_people = @people.group_by { |person| person[:score] }
                        .sort_by { |key, value| -key }     # largest -> smallest
                        .first(number)
                        .map(&:last)
                        .flatten
                        .map { |person| "#{person[:name]} (#{person[:score]})" }
                        .join(", ")
    puts "The top #{number} are here: #{top_people}"
end

供参考,使用 Ruby 2.3.3

标签: rubyclassoop

解决方案


我也尝试改进其他方面。我错过了更多的背景信息,但是将您的问题作为理论练习来回答,这就是我要做的:

 require 'faker'

 class ScoredPerson
  attr_reader :name
  attr_reader :score

  def initialize
    @name = Faker::Name.first_name
    @score = Faker::Number.between(1, 1000).to_i
  end
end

class TopPeople
  attr_accessor :people

  def initialize
    @people = 50.times.map do
      ScoredPerson.new
    end.sort_by { |p| p.score }.reverse
  end

  def top(number=10)
    people.first(number)
      .map { |p| "#{p.name} (#{p.score})"}.join(", ")
  end
end
  • 创建一个有序的人员列表(在一开始)。这将防止在每次调用该top方法时进行排序。
  • 创建一个ScoredPerson类来封装得分人的逻辑。

推荐阅读