是否有一种有效的方法来对数组数据(Javascript)执行高级“分面”过滤?

Is there an effective way to perform the advanced “faceted” filtering for the array data (with Javascript)?

我有一个数组:

var arr = [
["a", "b", "d"],
["k", "b", "n", "a"],
["k", "a", "e", "c"],
["k", "b", "e"],
["b", "c"]
]  

我想提取仅在包含 "a" 和 "b" 的子数组中出现的所有值。对于上面的示例,这些将​​是 ["d", "k", "n"].
当然,有一个明显的方法可以达到这个结果:

  1. 新建array/object,我们命名为result

  2. 迭代 arr。对于每个子数组,检查它是否包含 ["a", "b"] 的所有项目 - 如果是,则将其所有项目(可能除了 "a" 和 "b",但没关系)添加到 result(但在添加之前,我们可能想检查 result 中是否已经存在具有相同值的项目);如果没有,则跳过。

  3. 如果我们在添加之前没有检查我们的项目,那么从 result 中删除所有重复项。如果 result 按字母顺序排序,现在应该是 ["d", "k", "n"]

问题是这种方式似乎 缓慢且无效,特别是如果我在 arr 中有很多子数组并且没有太多不同的值:我会每次修改 ["a", "b"] 时都强制重复该过程!

构建这样的结构很容易:

 var s = [
{value: "a", siblings: ["b", "c", "d", "e", "k", "n"]},
{value: "b", siblings: ["a", "c", "d", "e", "k", "n"]},
{value: "c", siblings: ["a", "b", "e", "k"]},
{value: "d", siblings: ["a", "b"]},
{value: "e", siblings: ["a", "b", "c", "k"]},
{value: "k", siblings: ["a", "b", "c", "e", "n"]},
{value: "n", siblings: ["a", "b", "k"]}
]  

但是,如果我现在过滤所有在其 siblings 键中包含 ["a", "b"] 每个值的对象,我会得到 ["d", "e", "k", "n"],这是错误的。

所以,我想问:是否有可能构建一些看起来像

的智能“索引”结构
  var s = [
{value: "a", data: indexdata1},
{value: "b", data: indexdata2},
{value: "c", data: indexdata3},
{value: "d", data: indexdata4},
{value: "e", data: indexdata5},
{value: "k", data: indexdata6},
{value: "n", data: indexdata7}
]  

这样当我做 someFunc(s, ["a", "b"]) 时,它 returns [{value: "d"}, {value: "k"}, {value: "n"}]?无论如何,在 Javascript 中,什么可以被视为 有效 解决此问题的方法?是否有具有此类功能的现有库?
请注意,此问题与 eikes.github.io/facetedsearch 所做的不同(或者我找不到修改其代码的方法)。

采用不同方法的提案。不是对单个 items/letters 的视图,而是用找到的字母数组的索引组织一个对象 s

然后通过计数和过滤仅具有给定搜索长度 (c) 的字母来锐化它。使用 c.

剩余索引中的字母构建一个新对象 r

r 中删除给定的字母,获取密钥,对其排序并 return 结果。

function x(s, array) {
    var c = {}, r = {};
    array.forEach(function (a) {
        s[a].forEach(function (b) {
            c[b] = (c[b] || 0) + 1;
        });
    });
    document.write('<pre>c: ' + JSON.stringify(c, 0, 4) + '</pre>');
    Object.keys(c).filter(function (a) {
        return c[a] === array.length;
    }).forEach(function (a) {
        arr[a].forEach(function (b) {
            r[b] = true;
        });
    });
    document.write('<pre>r: ' + JSON.stringify(r, 0, 4) + '</pre>');
    array.forEach(function (a) {
        delete r[a];
    });
    document.write('<pre>r: ' + JSON.stringify(r, 0, 4) + '</pre>');
    return Object.keys(r).sort();
}

var arr = [
        ["a", "b", "d"],
        ["k", "b", "n", "a"],
        ["k", "a", "e", "c"],
        ["k", "b", "e"],
        ["b", "c"]
    ],
    s = arr.reduce(function (r, a, i) {
        a.forEach(function (b) {
            r[b] = r[b] || [];
            r[b].push(i);
        });
        return r;
    }, {});

document.write('<pre>s: ' + JSON.stringify(s, 0, 4) + '</pre>');
document.write('<pre>result: ' + JSON.stringify(x(s, ['a', 'b']), 0, 4) + '</pre>');