Временные преобразования в Ruby, Yahoo! Трубы стиль - PullRequest
1 голос
/ 07 мая 2010

Я пытаюсь создать систему для программной фильтрации данных временных рядов и задаюсь вопросом, была ли эта проблема решена или, по крайней мере, взломана ранее. Кажется, что это прекрасная возможность сделать магию блоков 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! Трубы делают это с кормом. Я не ищу слишком обобщенное решение прямо сейчас, я могу сделать формат массива / возвращает строгим.

Кто-нибудь видел что-нибудь подобное в Ruby? Или есть основные указатели?

1 Ответ

1 голос
/ 15 марта 2011

Первая половина вашего вопроса о работе в области действия массива кажется ненужной и неуместной для вашей проблемы. Что касается создания операций для манипулирования данными с блоками, вы можете использовать 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

Он также не использует патчей для обезьян!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...