过滤多个对象数组

时间:2015-03-06 15:44:25

标签: javascript arrays filter

我有以下情况:

有一些未定义的数组。每个数组都包含一些对象。这些对象中的每一个都有一个id元素,以及其他一些元素。

//Example objects:

f = [{'id': 1, 'name': 'a'}, {'id': 2, 'name': 'b'},
     {'id': 3, 'name': 'c'}, {'id': 1, 'name': 'd'}, ...]
g = [{'id': 2, 'name': 'e'}, {'id': 4, 'name': 'f'}, 
     {'id': 3, 'name': 'g'}, {'id': 4, 'name': 'h'}, ...]
h = ...
i = ...

我想过滤掉所有重复项,不仅在每个单独的数组中,而且在不同的数组中。

编辑:当id元素相同时,两个对象是重复的。优先级无关紧要,首次出现就好了。

我提出了以下功能:

function uniqueObjects() {
    var seen = [];
    for (var i=0; i<arguments.length; i++) {
        var arg = arguments[i];
        for (var j=0; j<arg.length; j++) {
            var elm = arg[j];
            var key = elm['id'];
            if (seen.indexOf(key) > -1) {
                arg.pop(elm);
            } else {
                seen.push(key);
            }
        }
    }
    return arguments;
}

但这似乎无法正常工作,因为我得到了以下值:

{'0': [{'id': 1, 'name': 'a'}, 
       {'id': 2, 'name': 'b'}, 
       {'id': 3, 'name': 'c'}], 
 '1': [{'id': 2, 'name': 'e'}, 
       {'id': 4, 'name': 'f'}]}

1 个答案:

答案 0 :(得分:2)

主要问题在于:

arg.pop(elm);

pop删除数组中的 last 元素,并且不接受任何参数。你可能意味着:

arg.splice(j, 1);

...但如果你这样做,那么你需要增加j。这样就给了我们:

function uniqueObjects() {
    var seen = [];
    for (var i=0; i<arguments.length; i++) {
        var arg = arguments[i];
        var j = 0;                       // **
        while (j<arg.length) {           // ** Made this a while loop
            var elm = arg[j];
            var key = elm['id'];
            if (seen.indexOf(key) > -1) {
                arg.splice(j, 1);         // ** Remove this entry
            } else {
                seen.push(key);
                ++j;                      // ** Increment j
            }
        }
    }
    return arguments;
}

但是,有一种更有效的方法可以跟踪您看到的id值:使用对象:

function uniqueObjects() {
    var seen = {};
    for (var i=0; i<arguments.length; i++) {
        var arg = arguments[i];
        var j = 0;
        while (j<arg.length) {
            var elm = arg[j];
            var key = " " + elm['id'];    // ** Note the space
            if (seen[key]) {              // ** Updated check
                arg.splice(j, 1);
            } else {
                seen[key] = true;         // ** Set the flag
                ++j;
            }
        }
    }
    return arguments;
}

为什么在创建id时将空格放在key之前?在 off-chance 上,您有id个值,其中包含对象上存在的名称,例如toStringvalueOf。 (ES6将引入Map个对象,我们不再需要这样做了。)

我还建议返回伪数组arguments,而是使用真正的数组。所以:

function uniqueObjects() {
    var seen = {};
    var args = Array.prototype.slice.call(arguments, 0); // <== Make real array
    for (var i=0; i<args.length; i++) {
        var arg = args[i];
        var j = 0;
        while (j<arg.length) {
            var elm = arg[j];
            var key = " " + elm['id'];    // ** Note the space
            if (seen[key]) {              // ** Updated check
                arg.splice(j, 1);
            } else {
                seen[key] = true;         // ** Set the flag
                ++j;
            }
        }
    }
    return args;
}

直播示例:

&#13;
&#13;
function uniqueObjects() {
    var seen = {};
    var args = Array.prototype.slice.call(arguments, 0);
    for (var i=0; i<args.length; i++) {
        var arg = args[i];
        var j = 0;
        while (j<arg.length) {
            var elm = arg[j];
            var key = " " + elm['id'];    // ** Note the space
            if (seen[key]) {              // ** Updated check
                arg.splice(j, 1);
            } else {
                seen[key] = true;         // ** Set the flag
                ++j;
            }
        }
    }
    return args;
}

var f = [
  {'id': 1, 'name': 'a'}, {'id': 2, 'name': 'b'},
  {'id': 3, 'name': 'c'}, {'id': 1, 'name': 'd'}
];
var g = [
  {'id': 2, 'name': 'e'}, {'id': 4, 'name': 'f'},
  {'id': 3, 'name': 'g'}, {'id': 4, 'name': 'h'}
];
snippet.log("Before: " + JSON.stringify([f, g]));
var result = uniqueObjects(f, g);
snippet.log("After: " + JSON.stringify(result));
&#13;
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
&#13;
&#13;
&#13;