【问题标题】:Fastest datastructure for filtering schema-less collections用于过滤无模式集合的最快数据结构
【发布时间】:2015-05-22 00:47:52
【问题描述】:

假设我有一个收藏

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

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

我想用_.findWhere 之类的东西过滤它。这很简单,但是如果我想优先考虑速度而不是轻松怎么办?是否有更好的数据结构可以始终最小化要检查的元素数量?也许是某种树?

【问题讨论】:

    标签: javascript algorithm data-structures collections


    【解决方案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。

    【讨论】:

    • 好答案。 OP表示该集合不是动态的。他可能只计算一次索引——如果它真的是静态的,甚至可以预先计算并加载它。
    • 这回答了_.where(collection, { fieldA: 5 }) 的情况。假设我想找到 2 个查询的交集(与 _.where(collection, { fieldA: 5, fieldB: 'string' }) 相同。在这种情况下,倒排索引查找将需要在两个查询结果中搜索交集——这不是恒定的,实际上比循环遍历 @ 更糟糕987654329@(我认为是 n*m?)
    • @NathanHagen - 错误;您只需要计算集合的并集 (OR) 或交集 (AND),这可以在 O(n+m) 中完成,其中 n 和 m 是集合的大小(通常远小于总文档数) ,假设它们是预购的。如果您的文档很少并且构建位掩码而不是数组,则可以更快地完成:您可以直接 AND 和 OR 位掩码...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 2011-04-07
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    相关资源
    最近更新 更多