【问题标题】:What's a good mathematical sets implementation in JavaScript?JavaScript 中什么是好的数学集合实现?
【发布时间】:2009-08-12 14:09:49
【问题描述】:

哪里有一个好的 JavaScript 数学集实现?它应该包括对交集、并集、补集和(对于加分)笛卡尔积的有效实现。

不,这不是家庭作业。我有一个 yubikey,它是一个 USB 键盘,可以键入从 16 个键码中选择的序列以键入 128 位一次性密码 (otp)。为了使其更有用,软件应根据生成的字符检测键盘布局,并将这些字符映射回它们在“us”布局中的样子,以便与现有后端兼容。

所以我有 93 个不同的 16 个字符序列,代表 yubikey 可以在 430 种键盘布局中键入的所有内容。 (为此目的,许多布局都是相同的。)特定 otp 的可能映射是每个 16 字符序列,其中包含 otp 中的每个字符。

为了有效地找到它,我使用反向索引将每个可能的字符映射到使用该字符的键盘布局列表。答案是 otp 中每个唯一字符的反向索引的每个条目的交集。这几乎总是以 1 个元素结束。

使用Set() 的良好实现来编写这个跨浏览器会更容易。

目前的代码位于http://dingoskidneys.com/~dholth/yubikey/

【问题讨论】:

  • 没有。我正在实现一个倒排索引,需要一个好的集合交集方法,而我发现的所有方法都很糟糕。

标签: javascript math set intersection


【解决方案1】:

通过使用 jPaq 或其他实现 Array.prototype.reduce 和 Array.prototype.forEach 函数的 JavaScript 库,您可以创建一个接受两个或多个数组的笛卡尔积函数。下面是计算两个或多个数组的笛卡尔积的函数的代码:

function cartesianProductOf() {
  return Array.prototype.reduce.call(arguments, function(a, b) {
    var ret = [];
    a.forEach(function(a) {
      b.forEach(function(b) {
        ret.push(a.concat([b]));
      });
    });
    return ret;
  }, [[]]);
}

至于这是在一个库中,我愿意接受有关函数命名的建议,以便我可以将它添加到jPaq。顺便说一句,为了不抄袭,我确实从this post得到了使用reduce的想法。

【讨论】:

    【解决方案2】:

    我不知道任何现有的实现,但如果您的 set 元素是字符串(或具有唯一的字符串表示),您可以很容易地使用 JavaScript 对象。元素是对象的属性,值可以是任何东西。

    // Make a set from an array of elements
    function makeSet(items) {
        var set = {};
        for (var i = 0; i < items.length; i++) {
            set[items[i]] = true;
        }
        return set;
    }
    
    function copyInto(s, copy) {
        for (var item in s) {
            if (s[item] === true) {
                copy[item] = true;
            }
        }
    }
    
    function union(s1, s2) {
        var u = {};
        copyInto(s1, u);
        copyInto(s2, u);
        return u;
    }
    
    function intersection(s1, s2) {
        var i = {};
        for (var item in s1) {
            if (s1[item] === true && s2[item] === true) {
                i[item] = true;
            }
        }
        return i;
    }
    
    function difference(s1, s2) {
        var diff = {};
        copyInto(s1, diff);
        for (var item in s2) {
            if (s2[item] === true) {
                delete diff[item];
            }
        }
        return diff;
    }
    
    // etc.
    

    您也可以使用item in setset.hasOwnProperty(item) 代替set[item] === true,但是通过显式检查true,您会自动忽略任何可能附加到对象的函数(如果有人修改了Object.prototype,或者它不是一个普通的对象)。

    【讨论】:

    • .hasOwnProperty 会比set[item]===true 更安全,不是吗?有人不能添加一个值为 true 的原型吗? Object.prototype.x = true
    • @Mark,是的,hasOwnProperty 在这种情况下会更安全,尽管这取决于您希望它的行为方式。在某些情况下,您可能希望原型中的属性显示在集合中。
    【解决方案3】:

    使用Underscore的reduce方法。

    function cartesianProductOf(){
        return _.reduce(arguments, function(mtrx, vals){
            return _.reduce(vals, function(array, val){
                return array.concat(
                    _.map(mtrx, function(row){ return row.concat(val); })
                );
            }, []);
        }, [[]]);
    }
    

    【讨论】:

      【解决方案4】:

      Sylvester 是一个很好的库,用于在 Javascript 中进行向量和矩阵数学运算。这是我目前唯一能想到的数学库。

      【讨论】:

        【解决方案5】:

        我个人喜欢 jPaq (http://jpaq.org/documentation/Arrays+as+Sets/1.0/) 中的工作方式。以下是我测试成功的三个示例:

        alert([1,2,3,4,5].subtract([2,3,5]));  // evaluates to [1,4]
        alert([1,2,5].union([1,3,4,5]));  // evaluates to [1,2,5,3,4]
        alert([1,2,3,5].intersect([0,1,2,4,6]));  // evaluates to [1,2]
        

        jPaq 的好处在于您可以只使用download the code for these three functions。 jPaq 做到了,因此您不必下载无论如何都不会使用的额外内容。

        【讨论】:

        • 另外,值得注意的是,jPaq 也有一个数组的 uniquify 函数。要下载它和设置的函数,你可以去这里:http://jpaq.org/download/1.0.1.0A
        【解决方案6】:

        我做了一个 JavaScript Set implementation 主要关注高效的differenceintersectionunion 操作。它可用at GitHub。非常欢迎分叉和新操作! :-)

        【讨论】:

        • 在您的实现中是否需要对集合进行排序?看起来您在实现中使用了某种二进制搜索,但如果元素不按顺序排列,这不会崩溃吗?
        • 你是对的,道格!我的实现很大程度上依赖于排序集合。这需要使用二分搜索并使我的交集算法也可以工作。但是没有排序算法,而是插入元素以确保其余部分正常工作。
        【解决方案7】:

        在引发这个问题的程序中,集合是一个数组,相交是

        s = [1,2,3];
        q = [3,4,5];
        sq = s.filter(function(x) {
            return q.indexOf(x) >= 0;
        });
        

        在ie中当然不行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-11
          • 1970-01-01
          • 2012-07-18
          • 2021-05-11
          • 2020-10-01
          • 2011-05-09
          • 1970-01-01
          相关资源
          最近更新 更多