根据子数组属性过滤数组中的唯一数据

时间:2014-11-05 02:57:06

标签: javascript arrays

我希望使用第二个属性过滤此数据以获得唯一的子数组,所以

var arr = [
    ["foo", "one"],
    ["bar", "one"],
    ["baz", "two"],
    ["qux", "two"]
]

应该变成

var arr = [
    ["foo", "one"],
    ["baz", "two"]
]

我可以尝试使用两个嵌套forEach的手动方法,但这似乎效率低下。 Array.prototype.filter似乎更适合,但我担心我缺乏正确使用它的经验。

5 个答案:

答案 0 :(得分:2)

另一个版本(假设您的arr定义存在):

arr = arr.filter(function(innerArr){
  return !this[innerArr[1]] && (this[innerArr[1]]=true)
},{})

答案 1 :(得分:1)

  1. 将要保留的数组与数组的第二个元素一起存储在Object中。这是为了避免重复。

    var obj = {};
    
    arr.forEach(function(currentArray) {
        if (obj.hasOwnProperty(currentArray[1]) === false) {
            obj[currentArray[1]] = currentArray;
        }
    });
    
  2. 然后单独收集值,就像这样

    var result = [];
    for (var key in obj) {
        result.push(obj[key]);
    }
    
    console.log(result);
    # [ [ 'foo', 'one' ], [ 'baz', 'two' ] ]
    
  3. 此解决方案的运行时间为O(N)。

    注意:此解决方案可能无法保证结果中的项目顺序。

答案 2 :(得分:1)

以下是我想要的。 http://jsfiddle.net/pitaj/ktj06Ljt/

var seenit = []; // array to store properties already found

var newarr = arr.filter(function(it){ 
  var result = seenit.indexOf(it[1]) === -1; // check if already found
  seenit.push(it[1]); // add to found array
  return result; // return if it was found, as per filter
});

这种方式将使它们保持与原始顺序相同的顺序。

编辑:替代方案,你可以在没有外部数组的情况下完成(正如Cheery指出的那样):

var newarr = arr.filter(function(it){ 
  var result = this.indexOf(it[1]) === -1;
  this.push(it[1]); 
  return result;
}, []);

http://jsfiddle.net/jdLz4gm7/

答案 3 :(得分:1)

也许是这样的:

var arr = [
    ["foo", "one"],
    ["bar", "one"],
    ["baz", "two"],
    ["qux", "two"]
];
var uniques=[
  Object.create(null),
  Object.create(null)
];
var result=arr.filter(function(item_set){
  return item_set.every(function(item,idx){
    var u=!uniques[idx][item];
    uniques[idx][item]=true;
    return u;
  });
});

/*
result=[["foo", "one"], ["baz", "two"]];
*/

*更正:将uniques[item]更改为uniques[idx][item],以便该对中的每个项目都可以访问自己的查找表。

答案 4 :(得分:0)

使用underscore.js,您只需输入以下代码:

_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]

更新

我很抱歉我误解了你的问题,上面的答案是错误的 我为你的问题写了一个新的演示:http://jsfiddle.net/abruzzi/0an5yr9c/2/
以下是代码:

var arr = [
    ["foo", "one"],
    ["bar", "one"],
    ["baz", "two"],
    ["qux", "two"]
];

var uniq = [];
var result = arr.filter(function(sub_arr){
    return sub_arr.every(function(sub_item){
        if(uniq.indexOf(sub_item) < 0) {
            uniq.push(sub_item);
            return true;
        }
        return false;
    });
})

result => [
    ["foo", "one"],
    ["baz", "two"]
]