Ruby on rails 我试图在Ruby Array类的每次运行中添加一个方法,该方法接受一个需要两个参数的代码块
在Ruby数组类中添加一个每次运行的方法,该类接受一个需要两个参数的代码块。它为数组中相等项的每个连续运行调用一次代码块,发送运行长度和重复的项。输出如下所示:Ruby on rails 我试图在Ruby Array类的每次运行中添加一个方法,该方法接受一个需要两个参数的代码块,ruby-on-rails,ruby,rubygems,Ruby On Rails,Ruby,Rubygems,在Ruby数组类中添加一个每次运行的方法,该类接受一个需要两个参数的代码块。它为数组中相等项的每个连续运行调用一次代码块,发送运行长度和重复的项。输出如下所示: irb(main):001:0> load("eachrun.rb") => true irb(main):002:0> [5,9,3,4,4,4,7,8,8].each_run { |n,x| irb(main):003:1* print x, " appearing ", n, " t
irb(main):001:0> load("eachrun.rb")
=> true
irb(main):002:0> [5,9,3,4,4,4,7,8,8].each_run { |n,x|
irb(main):003:1* print x, " appearing ", n, " times\n" }
5 appearing 1 times
9 appearing 1 times
3 appearing 1 times
4 appearing 3 times
7 appearing 1 times
8 appearing 2 times
=> nil
这可能会给你一些关于如何继续的想法:
irb(main):001:0> a = [5,9,3,4,4,4,7,8,8]
=> [5, 9, 3, 4, 4, 4, 7, 8, 8]
irb(main):002:0> a.uniq.each { |e| printf("%d appears %d times\n", e, a.count(e)) }
5 appears 1 times
9 appears 1 times
3 appears 1 times
4 appears 3 times
7 appears 1 times
8 appears 2 times
我同意使用uniq和each的建议,但这只是在需要将uniq值作为数组返回的情况下。有很多方法可以迭代,这取决于你自己,但这里的关键是猴子补丁和产生你的值,以便使用块
资料来源:
我将使用
groupby
并生成相关组的键和大小
def each_run
group_by(&:itself).map {|k,v| yield v.length, k }
end
不过,我不会将它直接修补到数组中。首先,作为可枚举
的一部分,它更有意义,其次,猴子补丁可能会变得混乱。不过,你可以把它做得更精致。遗憾的是,您只能优化类,而不能优化模块,因此它回到了Array
而不是Enumerable
:
module EachRun
refine Array do
def each_run
group_by(&:itself).map {|k,v| yield v.length, k }
end
end
end
然后,只需将使用EachRun
放在您希望能够使用新方法的任何代码的顶部。我了解了问题的意图“它为数组中相同项的每个连续运行调用代码块一次”因为示例列表不包含数字的后续运行,所以您可以忽略输入列表的结构,只计算任何给定项目出现的次数,所以示例列表是一种误导。如果例子是:
[5,9,3,4,4,4,7,8,8,5,5]
那么,打印“5出现3次”并不表明自己是正确的
我已经有一段时间没有写任何Ruby了,所以这可能不是最优的,但这正是我想到的:
require 'test/unit/assertions'
include Test::Unit::Assertions
module Enumerable
def runs
if empty?
[]
else
runs = [[first,1]]
self[1..-1].each do |item|
if item == runs.last.first
runs = runs[0..-2] + [[item,runs.last.last+1]]
else
runs = runs + [[item,1]]
end
end
runs
end
end
def each_run(&block)
runs.each(&block)
end
end
assert_equal( [], [].runs )
assert_equal( [[5,1],[9,1],[3,1],[4,3],[7,1],[8,2],[5,2]], [5,9,3,4,4,4,7,8,8,5,5].runs )
[5,9,3,4,4,4,7,8,8,5,5].each_run do |m,n|
puts "#{m} appears #{n} times"
end
输出
> 5 appears 1 times
> 9 appears 1 times
> 3 appears 1 times
> 4 appears 3 times
> 7 appears 1 times
> 8 appears 2 times
> 5 appears 2 times
当我在Clojure中思考时,我想到的是:
(defn runs [l]
(reduce (fn [memo [x n :as e]]
(let [[last-x last-n] (last memo)]
(if (= x last-x)
(conj (vec (drop-last memo)) [x (inc last-n)])
(conj memo e))))
[] (map (fn [e] [e 1]) l)))
(runs [5 5 9 8 1 1 4 3 3 3 3 5 5 5 2 2])
=> [[5 2] [9 1] [8 1] [1 2] [4 1] [3 4] [5 3] [2 2]]
很好,祝你好运
> 5 appears 1 times
> 9 appears 1 times
> 3 appears 1 times
> 4 appears 3 times
> 7 appears 1 times
> 8 appears 2 times
> 5 appears 2 times
(defn runs [l]
(reduce (fn [memo [x n :as e]]
(let [[last-x last-n] (last memo)]
(if (= x last-x)
(conj (vec (drop-last memo)) [x (inc last-n)])
(conj memo e))))
[] (map (fn [e] [e 1]) l)))
(runs [5 5 9 8 1 1 4 3 3 3 3 5 5 5 2 2])
=> [[5 2] [9 1] [8 1] [1 2] [4 1] [3 4] [5 3] [2 2]]