用于将散列合并到稀疏矩阵中的高效算法

时间:2012-02-20 08:02:29

标签: ruby algorithm sparse-matrix

我有不规则间隔的时间数据,我需要将其转换为稀疏矩阵,以便与图形库一起使用。

数据目前采用以下格式:

{
  :series1 => [entry, entry, entry, entry, ...],
  :series2 => [entry, entry, entry, entry, ...]
}

其中entry是具有两个属性的对象timestamp(unix时间戳)和value(整数) 我需要尽可能接近O(n)时间将它放在这种格式中。

{
   timestamp1 => [ value, value, nil ],
   timestamp2 => [ value, nil, value ],
   timestamp3 => [ value, value, value],
   ...
}

这里每行代表一个我有条目的时间点。每列代表一个系列(折线图上的一条线)。这就是为什么用nil表示缺失值非常重要。

我有一些非常慢的实现,但这似乎是一个已经解决的问题所以我希望有更有效的方法来做到这一点。

2 个答案:

答案 0 :(得分:1)

我对你要求O(n)感到有些困惑,所以请随意纠正我,但据我所知,O(n)很容易实现。

首先找到起始哈希的长度(数据中的序列数)。这应该是O(1),但不比O(S)(其中S不是系列)更差,并且S< = O(n)(假设没有没有值的系列),因此仍然是O(n)。

将此长度存储在某处,然后为稀疏矩阵设置散列,以自动将任何行初始化为此大小的空数组。

matrix = Hash.new {|hsh,k| hsh[k] = Array.new(S)}

然后通过索引简单地浏览每个系列。对于每个条目,将数组中的相应单元格设置为正确的值。

对于每个条目,这是用于查找散列中的时间戳的O(1)(平均值),然后是用于设置阵列中的单元的O(1)。这种情况发生了n次,给你O(n)。

还会为矩阵中的每一行创建一个数组。据我所知,对于一个数组,这是O(1),所以O(T)(其中T是时间戳的数量)总体而言。因为我们没有创建没有带有该时间戳的条目的空行,所以T必须是< = n,所以这也是O(n)。

总的来说,我们有O(n)+ O(n)+ O(n)= O(n)。有可能在Ruby中加快速度,但据我所知,这不仅接近,而且实际上是O(n)。

答案 1 :(得分:0)

这样的事情怎么样:

num = series.count
timestamps = {}
series.each_with_index do |(k, entries), i|
  entries.each do |entry|
    timestamps[entry.timestamp] ||= Array.new(num)
    timestamps[entry.timestamp][i] = entry.value
  end
end

虽然不确定系列的初始排序,但我猜你的实际情况比问题中提到的要复杂一些。