目前,我正在这样做:
(in initialize)
@all = Stuff.all.each.map {|t| t.reference_date }
@uniques = @all.uniq
results = []
@uniques.each do |k|
i = 0
@all.each do |x|
i += 1 if x =~ %r{#{x}}
end
results << [k, i]
end
那没关系。它会起作用。但我喜欢在可以的时候避免使用正则表达式。我觉得他们有点feo。那是丑陋的西班牙语。
EDIT--
实际上,这是行不通的,因为当日期对象放在字符串内部(作为变量,这里)时,ruby将日期作为2012-03-31
的编号格式“放置”,但它实际上是一个日期对象,所以这个工作:
if x.month == k.month && x.day == k.day
i += 1
end
答案 0 :(得分:2)
你可以只用一行(如果我当然是正确的话):
array = %w(a b c d a b d f t z z w w)
# => ["a", "b", "c", "d", "a", "b", "d", "f", "t", "z", "z", "w", "w"]
array.uniq.map{|i|[i, array.count(i)]}
# => [["a", 2], ["b", 2], ["c", 1], ["d", 2], ["f", 1], ["t", 1], ["z", 2], ["w", 2]]
答案 1 :(得分:1)
results = Hash.new(0)
@all.each{|t| results[t] += 1}
# stop here if a hash is good enough.
# if you want a nested array:
results = results.to_a
这是获取可枚举元素频率的标准方法。
答案 2 :(得分:1)
要避免正则表达式的外观,您可以使用Regexp.union
动态构建它们。您可能想要这样做的原因是SPEED。构造良好的正则表达式比迭代列表更快,尤其是大型列表。并且,通过允许您的代码构建正则表达式,您不必维护一些丑陋(feo)的东西。
例如,这是我在不同的代码块中所做的事情:
words = %w[peer_address peer_port ssl ssl_protocol ssl_key_exchange ssl_cipher]
regex = /\b(?:#{ Regexp.union(words).source })\b/i
=> /\b(?:peer_address|peer_port|ssl|ssl_protocol|ssl_key_exchange|ssl_cipher)\b/i
这使维持正则表达式变得微不足道。并且,尝试使用该基准来查找文本中的子字符串以反对迭代,它会给您留下深刻的印象。
答案 3 :(得分:0)
如果通配符适合您,请尝试File.fnmatch
答案 4 :(得分:0)
从您的代码中我感觉您想获得每个reference_date
的出现次数。通过直接使用ActiveRecord和SQL而不是拉动整个故事然后在Ruby中执行耗时的操作,可以更容易地实现这一点。
如果您使用的是Rails 2.x,您可以使用以下内容:
Stuff.find(:all, :select => "reference_date, COUNT(*)", :group => "reference_date")
或者如果您使用的是Rails 3,那么您可以将其简化为
Stuff.count(:group => "reference_date")