JavaScript中的数学集合实现是什么?

时间:2009-08-12 14:09:49

标签: javascript math set intersection

JavaScript的数学集合实现在哪里?它应该包括交叉,联合,补充和(对于奖励积分)笛卡尔积的有效实现。

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

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

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

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

到目前为止,

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

7 个答案:

答案 0 :(得分:11)

通过使用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的想法。

答案 1 :(得分:6)

我不知道任何现有的实现,但如果您的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,或者它不是普通对象。)

答案 2 :(得分:2)

使用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); })
            );
        }, []);
    }, [[]]);
}

答案 3 :(得分:1)

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

答案 4 :(得分:1)

我个人喜欢在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使你不必下载你不会使用的额外东西。

答案 5 :(得分:1)

我做了一个JavaScript Set implementation,主要关注有效的differenceintersectionunion操作。它可用at GitHub。福克斯和新业务非常受欢迎! : - )

答案 6 :(得分:0)

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

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

当然它在ie。

中不起作用