在哈希表中增加数值

4
我有一堆带有类别标签的文章。 我想知道每个类别已经被使用了多少次。
我正在使用Rails和MongoDB,但我认为我不需要从数据库中获取类别出现的次数,所以Mongo部分应该无关紧要。
这是我目前的代码:
@recent_posts = current_user.recent_posts #返回最近的10篇文章 @categories_hash = {'tech' => 0, 'world' => 0, 'entertainment' => 0, 'sports' => 0} @recent_posts.each do |post| post.categories.each do |category| @categories_hash[category] += 1 #显然,这是我遇到问题的地方 end end
文章的结构如下:
{"_id" : ObjectId("idnumber"), "created_at" : "Tue Aug 03...", "categories" :["world", "sports"], "message" : "the text of the post", "poster_id" : ObjectId("idOfUserPoster"), "voters" : []}
我欢迎任何其他获取类别计数的建议,但我最终会想要获取投票人数,所以对我来说似乎最好的方法是增加categories_hash的值,然后再添加voters.length,但是一步一步来,我只是试图弄清楚如何递增哈希中的值。
2个回答

9
如果您不熟悉map/reduce并且不关心扩展性,那么这种方法可能没有map/reduce的优雅,但对于小型网站来说应该已经足够了。
@categories_hash = Hash.new(0)
current_user.recent_posts.each do |post|
  post.categories.each do |category|
    @categories_hash[category] += 1
  end
end

3
如果你将第一行改为@categories_hash = Hash.new(0),或者像原问题中那样初始化它,就可以删除 @categories_hash[category] ||= 0 这一行。 - Sophie Alpert

1
如果您正在使用mongodb,一种优雅的聚合标签使用方法是使用map/reduce操作。Mongodb支持使用JavaScript代码进行map/reduce操作。Map/reduce在db服务器上运行,即您的应用程序不必检索和分析每个文档(这对于大型集合来说不会很好扩展)。
例如,在我的博客文章集合中使用以下映射和减少函数来聚合标签的使用情况(用于构建侧边栏中的标签云)。文章集合中的文档具有名为“tags”的键,其中包含字符串数组(标签)。
映射函数只需在每个使用的标签上发出1以计数:
function () {
  if (this.tags) {
    this.tags.forEach(function (tag) {
      emit(tag, 1);
    });
  }
}

reduce 函数将计数相加:

function (key, values) {
  var total = 0;
  values.forEach(function (v) {
    total += v;
  });
  return total;
}

作为结果,数据库返回一个哈希表,其中每个标签都有一个键和其使用计数作为值。例如:
{ 'rails' => 5, 'ruby' => 12, 'linux' => 3 }

好吧,我一直想学习和使用map/reduce,但我认为可能有更简单的方法来使用Ruby完成这个任务,不过我会尝试你的方法并回报结果。 - pedalpete
这在Ruby中确实更容易处理,但效率较低,不过对于小网站仍可能足够。我发布了另一个使用您原始代码变体的答案。 - Zargony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接