2

我想知道如何检查数组中的重复值对是否作为javascript中较大数组的一部分存在。你可以看到有一对重复的[1,2]- 所以函数应该只是 return true。IE

var arr = [[1,2], [3,4], [5,6], [7,8], [9,10], [11,12], [13,14], [1,2]]

我试过使用这个逻辑,它给了我一个干净的数组和一个“真”

var unique = [];
var done = []; var dup = false;
for(var x = 0; x < arr.length; x++) {
    var myStr = arr[x].toString();

    if(done.indexOf(myStr) != -1) {
        // val already exist, ignore
        dup = true;
        continue;
    }

    done.push(myStr);
    unique.push(arr[x]);
}

但我想知道使用 Underscore 是否有更优雅的东西?

4

3 回答 3

5

最短的方法是使用_.uniqand JSON.stringify

function unique(arr) {
    return _.uniq(arr, JSON.stringify).length === arr.length;
}

但这不会短路,因此与您可以做到的其他方式相比,它有点慢。Tomalak 的第二个功能应该更快。

于 2013-05-26T17:52:09.353 回答
2

嗯,uniq看起来很合适

function containsDuplicates(arr) {
  return arr.length !== _.uniq(arr, function (item) { return item.toString(); }).length;
}

你应该使用 Blender 版本的这个函数。它更短更安全。


顺便说一句,您的代码应该看起来更像这样:

function containsDuplicates(arr) {
    var index = {}, i, str;

    for(i = 0; i < arr.length; i++) {
        // you could use arr[i].toString() here, but JSON.stringify()
        // is a lot safer because it cannot create ambiguous output.
        str = JSON.stringify(arr[i]);
        if (index.hasOwnProperty(str)) {
            return true;
        } else {
            index[str] = true;
        }
    }

    return false;
}

请注意,这可能比下划线单行更有效。

于 2013-05-26T17:51:00.253 回答
2

尽管大多数时候stringify是答案,它仍然存在问题,例如{"x":1,"y":2}并且{"y":2,"x":1}被认为是不同的。如果您需要 100% 准确的比较,则没有其他方法可以存储已处理的对象并对其进行深度比较(幸运的是,下划线为此提供了一个实用程序)。

uniq2 = function(xs) {
    return _.reduce(xs, function(result, x) {
        if(!_.any(result, _.partial(_.isEqual, x)))
            result.push(x);
        return result;
    }, []);
}

测试:

var arr = [[1,2], [3,4], "1,2", "[1,2]", [1,2], {x:1,y:2}, {y:2,x:1}]
console.log(uniq2(arr))
// [[1,2],[3,4],"1,2","[1,2]",{"x":1,"y":2}]

在最坏的情况下,这将是二次的,但没有其他方法。

于 2013-05-26T18:30:17.323 回答