我正在尝试构建一个系统,用于以编程方式过滤时间序列数据,并想知道这个问题是否已经解决,或者至少已经被黑客攻击过了。考虑到范围和传球能力,这似乎是一个完美的机会来做一些Ruby块魔法;但是,我仍然没有完全了解如何利用积木。
即便:
从我的数据库中提取数据,我可以创建一个哈希或一个数组,让我们使用数组:
data = [[timestamp0, value0],[timestamp1,value1], … [timestampN, valueN]]
然后我可以为数组添加一个方法,可能是这样的:
class Array
def filter &block
…
self.each_with_index do |v, i|
…
# Always call with timestep, value, index
block.call(v[0], v[1], i)
…
end
end
end
我理解Ruby块的一个功能是传递的代码块发生在闭包范围内。所以以某种方式调用data.filter应该允许我使用该范围。我只能在不利用范围的情况下弄清楚如何做到这一点。即:
# average if we have a single null value, assumes data is correctly ordered
data.filter do |t, v, i|
# Of course, we do some error checking…
(data[i-1] + data[i+1]) / 2 if v.nil?
end
我想要做的实际上是(允许用户)以编程方式构建数学过滤器,但是一次一步,我们将构建一些函数:
def average_single_values(args)
#average over single null values
#return filterable array
end
def filter_by_std(args)
#limit results to those within N standard deviations
#return filterable array
end
def pull_bad_values(args)
#delete or replace values seen as "bad"
#return filterable array
end
my_filters == [average_single_values, filter_by_std, pull_bad_values]
然后,有了一个过滤器列表,我想(不知何故)我应该能够做到:
data.filter do |t, v, i|
my_filters.each do |f|
f.call t, v, i
end
end
或者,假设一个不同的过滤器实现:
filtered_data = data.filter my_filters
这可能是设计它的更好方法,因为它返回一个新数组并且是非破坏性的
结果是一个已经遍历所有过滤器的数组。最终的目标是能够拥有可以通过任意过滤器运行的静态数据数组,以及可以像Yahoo!那样的方式作为对象传递(和共享)的过滤器。管道使用Feed进行管理。我现在不是在寻找太普遍的解决方案,我可以使数组的格式/返回严格。
有没有人在Ruby中看过类似的东西?或者有一些基本的指示?
答案 0 :(得分:1)
关于在数组范围内工作的问题的前半部分似乎是不必要的,与您的问题无关。至于创建使用块操作数据的操作,可以使用Proc
实例(“procs”),它们实际上是存储在对象中的块。例如,如果要使用名称存储它们,可以创建过滤器的哈希值:
my_filters = {}
my_filters[:filter_name] = lambda do |*args|
# filter body here...
end
当然,您不需要为它们命名,并且可以使用数组。然后,要通过一系列有序过滤器运行某些数据,请使用有用的Enumerable#inject
方法:
my_filters.inject(data) do |result, filter|
filter.call result
end
它也没有使用monkeypatching!