【问题标题】:How to find the most frequent multiple values in array如何在数组中找到最频繁的多个值
【发布时间】:2021-04-01 18:51:55
【问题描述】:

我有一组对象“订单”,其中包括书籍/读者/日期

我需要获得顶级读者(即阅读最多书籍的读者) 并且返回的热门阅读器的数量必须是可配置的。默认数量为 1 个阅读器

这是 16 个订单的输出

 [#<Order:0x0000562626492558 @book="Codename: American Man", @reader="Mariel Beier", @date="30.03.2021">, 
    #<Order:0x00005626264924e0 @book="Forbidden Wizard", @reader="Mariel Beier", @date="30.03.2021">,
     #<Order:0x0000562626492468 @book="Action Ninja", @reader="Taryn Gutmann", @date="30.03.2021">,
     #<Order:0x00005626264923f0 @book="Action Ninja", @reader="Garret Lindgren", @date="30.03.2021">, 
    #<Order:0x0000562626492378 @book="Forbidden Wizard", @reader="Alysa Keeling", @date="30.03.2021">, 
    #<Order:0x0000562626492300 @book="War of the American Imp", @reader="Garrett Stroman", @date="30.03.2021">, 
    #<Order:0x0000562626492288 @book="Blue Witch", @reader="Garrett Stroman", @date="30.03.2021">, 
    #<Order:0x0000562626492210 @book="War of the American Imp", @reader="Sherlyn Schumm", @date="30.03.2021">, 
    #<Order:0x0000562626492198 @book="Action Ninja", @reader="Mac Funk", @date="30.03.2021">, 
    #<Order:0x0000562626492120 @book="Forbidden Wizard", @reader="Mariel Beier", @date="30.03.2021">, 
    #<Order:0x00005626264920a8 @book="The Nuclear Wolves", @reader="Les Conn", @date="30.03.2021">, 
    #<Order:0x0000562626492030 @book="War of the American Imp", @reader="Taryn Gutmann", @date="30.03.2021">, 
    #<Order:0x0000562626491fb8 @book="War of the American Imp", @reader="Les Conn", @date="30.03.2021">, 
    #<Order:0x0000562626491f40 @book="The Nuclear Wolves", @reader="Les Conn", @date="30.03.2021">, 
    #<Order:0x0000562626491ec8 @book="Action Ninja", @reader="Diamond Cole", @date="30.03.2021">, 
    #<Order:0x0000562626491e50 @book="Action Ninja", @reader="Garret Lindgren", @date="30.03.2021">]

基本上我需要通过关键字(书籍/读者/最受欢迎的作者)来获取模式

我正在使用 ffaker 为这个数组生成随机数据

  def build_author
    name = FFaker::Book.author
    biography = FFaker::Book.description
    Author.new(name, biography)
  end

  def build_book(author)
    title = FFaker::Book.title
    Book.new(title, author.name)
  end

  def build_reader
    name = FFaker::Name.name
    email = FFaker::Internet.email
    city = FFaker::Address.city
    street = FFaker::Address.street_name
    house = rand(1 - 10_000)
    Reader.new(name, email, city, street, house)
  end

  def build_order(book, reader)
    date = Time.now.utc.strftime('%d.%m.%Y')
    Order.new(book.title, reader.name, date)
  end

  def fill_author
    3.times do
      author = build_author
      @authors.push(author)
    end
  end

  def fill_book
    6.times do
      book = build_book(@authors.sample)
      @books.push(book)
    end
  end

  def fill_reader
    10.times do
      reader = build_reader
      @readers.push(reader)
    end
  end

  def fill_order
    16.times do
      @orders.push(build_order(@books.sample, @readers.sample))
    end
  end

这里是主库类

class Library
  include DataBuilder
  include Statistics

  attr_accessor :authors, :books, :orders, :readers

  def initialize(authors: [], books: [], orders: [], readers: [])
    @books = books
    @orders = orders
    @readers = readers
    @authors = authors
  end

  def create_data
    create_arrays
    generate_data
  end

  def show
    create_data
    p top_reader
  end

编辑:

我现在如何获得顶级读者/书籍

  def top_reader
    orders_grouped = orders.group_by(&:reader)
    tab = orders_grouped.max_by { |_k, v| v.count }.first
    puts "#{tab} is the top reader"
  end

  def top_book
    orders_grouped = orders.group_by(&:book)
    tab = orders_grouped.max_by { |_k, v| v.count }.first
    puts "#{tab} is the top book"
  end

这是一个输出:

Mariel Beier is the top reader
Action Ninja is the top book

还不知道如何配置顶级读者/书籍的数量

【问题讨论】:

  • 模型/关系是什么样子的,你能发布那个代码吗?
  • @Int'lManOfCodingMystery 编码之谜已更新。我只需要让购买最多书籍的读者。还有最畅销的书

标签: ruby-on-rails ruby


【解决方案1】:

对不起,我简化了一点以专注于手头的问题(至少我对它的理解)

class Order
  attr_reader :book, :reader, :date
  def initialize(b,r,d)
    @book = b
    @reader = r
    @date = d
  end
end

orders = [
  Order.new("Codename: American Man", "Mariel Beier", "30.03.2021"),
  Order.new("Forbidden Wizard", "Mariel Beier", "30.03.2021"),
  Order.new("Action Ninja", "Taryn Gutmann", "30.03.2021"),
  Order.new("Action Ninja", "Garret Lindgren", "30.03.2021"),
  Order.new("Forbidden Wizard", "Alysa Keeling", "30.03.2021"),
  Order.new("War of the American Imp", "Garrett Stroman", "30.03.2021"),
  Order.new("Blue Witch", "Garrett Stroman", "30.03.2021"),
  Order.new("War of the American Imp", "Sherlyn Schumm", "30.03.2021"),
  Order.new("Action Ninja", "Mac Funk", "30.03.2021"),
  Order.new("Forbidden Wizard", "Mariel Beier", "30.03.2021"),
  Order.new("The Nuclear Wolves", "Les Conn", "30.03.2021"),
  Order.new("War of the American Imp", "Taryn Gutmann", "30.03.2021"),
  Order.new("War of the American Imp", "Les Conn", "30.03.2021"),
  Order.new("The Nuclear Wolves", "Les Conn", "30.03.2021"),
  Order.new("Action Ninja", "Diamond Cole", "30.03.2021"),
  Order.new("Action Ninja", "Garret Lindgren", "30.03.2021")
]

编辑:正如Cary Swoveland 指出的那样,有一种更好的方法(比对整个哈希进行排序)来获得给定数量的“排名靠前的人”:

def top_rankers( orders, filter, count = 1)
  hash = Hash.new(0)
  orders.each do |order|
    hash[order.public_send(filter)] += 1
  end
  hash.max_by(count, &:last)
end

或者更简洁的方式

def top_rankers( orders, filter, count = 1 )
  orders.each_with_object(Hash.new(0)) { |o,h| h[o.public_send(filter)] += 1 }.max_by(count, &:last)
end

这会给你一个易于操作的结果:

top_rankers(orders, :reader, 5)
# => [["Les Conn", 3], ["Mariel Beier", 3], ["Garret Lindgren", 2], ["Taryn Gutmann", 2], ["Garrett Stroman", 2]]

top_rankers(orders, :reader, 3).map(&:first)
# => ["Les Conn", "Mariel Beier", "Garrett Stroman"]

top_rankers(orders, :book)
# => [["Action Ninja", 5]]

top_rankers(orders, :book, 2).to_h
# => {"Action Ninja"=>5, "War of the American Imp"=>4}

【讨论】:

  • 谢谢Carry,我永远不会停止和你一起学习 :-) 我没想到Enumerable#max_byEnumerable#sort_by 更符合规格
  • 比方说top_nbr_readers = 1,当有多个“阅读数”相同的阅读器时,我不确定该怎么办,丢弃不走运的?
  • 这取决于要求。如果需要所有并列的顶级读者,您需要获得top_nbr_readersth 读者阅读的书籍数量,例如N,然后选择至少阅读过N 书籍的所有读者。无需在您的答案中注明出处。好几次我都放弃了我的整个答案,用评论者提出的建议代替它(感谢评论中的那个人)。
  • 感谢您的帮助!现在我正在获得顶级读者/书籍,但不知道如何获得前 2-3 名
  • @Danyil,你应该考虑# =&gt; 的行。我的top_ranker 函数能给你什么?
【解决方案2】:

您可以使用 group_by 的组合为每个读者分组书籍,并使用 sort_by 对读者进行排序

  orders_grouped = orders.group_by { |order| order.reader }
  tab = orders_grouped.sort_by { |k,v| v.uniq.size }.reverse!

使用哈希和三个一阶的标签输出

[["Mariel Beier", [{:book=>"Codename: American Man", :reader=>"Mariel Beier", :date=>"30.03.2021"}, {:book=>"Forbidden Wizard", :reader=>"Mariel Beier", :date=>"30.03.2021"}]],
 ["Taryn Gutmann", [{:book=>"Action Ninja", :reader=>"Taryn Gutmann", :date=>"30.03.2021"}]]]

那么你可以像这样带数量的读者

tab[0..quantity-1]

【讨论】:

  • 在尝试获得顶级读者Invasion of the Ultra Woman was bought by Tiesha Blanda at 31.03.2021 Curse of the Forbidden Identity was bought by Tiesha Blanda at 31.03.2021 War of the Killer Cat was bought by Tiesha Blanda at 31.03.2021 I am Tokyo Thief was bought by Tiesha Blanda at 31.03.2021 时给我下一个输出。我怎样才能得到读者的名字?
  • 访问返回值的第一个元素获取top reader
  • 感谢您的帮助!现在我正在获得顶级读者/书籍,但不知道如何获得前 2-3 名
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多