用于过滤无模式集合的最快数据结构

时间:2015-03-19 01:10:09

标签: javascript algorithm data-structures collections

假设我有一个集合

var data = [
  { fieldA: 5 },
  { fieldA: 142, fieldB: 'string' },
  { fieldA: 1324, fieldC: 'string' },
  { fieldB: 'string', fieldD: 111, fieldZ: 'somestring' },
  ...
];

让我们假设各个元素的字段不一致,但我事先知道唯一字段的数量,并且该集合不是动态的。

我想用_.findWhere之类的东西过滤它。这很简单,但如果我想优先考虑速度优先呢?是否有更好的数据结构,总是最小化将要检查的元素数量?也许某种树?

1 个答案:

答案 0 :(得分:1)

是的,如果您的查询属于“使用fieldX = valueY给我所有记录”,那么会有更快的速度。但是,它确实有开销。

对于每个字段,构建一个倒排索引,列出具有每个值的所有记录ID(=原始data中的行位置):

var indexForEachField = {
    fieldA: { "5": [0], "142": [1], "1324": [2]},
    ...
}

当有人要求“其中fieldX = valueY的记录”时,您将返回

indexForEachField["fieldX"]["valueY"]; // an array with all results

因此查找时间不变(并且表中只需要2次查找),但您需要保持索引最新。

这是搜索引擎使用某些术语查找网页的策略的概括;在那种情况下,它被称为inverted index


编辑:如果您想查找fieldX = valueX fieldY = valueY的所有记录,该怎么办?

您将使用以下代码,该代码需要所有输入数组 待分类:

var a = indexForEachField["fieldX"]["valueX"];
var b = indexForEachField["fieldY"]["valueY"];
var c = []; // result array: all elements in a AND in b
for (var i=0, j=0; i<a.length && j<b.length; /**/) {
    if (a[i] < b[j]) {
       i++;
    } else if (a[i] > b[j]) {
       j++;
    } else {
       c.push(a[i]);
       i++; j++;
    }
}

你可以看到,在最坏的情况下,总复杂度正是a.length + b.length;而且,在最好的情况下,一半。您可以使用非常类似的东西来实现OR。