javascript 使用javascript从数组中删除重复的对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19501441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:48:21  来源:igfitidea点击:

Remove duplicate objects from an array using javascript

javascriptarraysalgorithmsorting

提问by Lion789

I am trying to figure out an efficient way to remove objects that are duplicates from an array and looking for the most efficient answer. I looked around the internet everything seems to be using primitive data... or not scalable for large arrays. This is my current implementation which is can be improved and want to try to avoid labels.

我试图找出一种有效的方法来从数组中删除重复的对象并寻找最有效的答案。我环顾互联网,似乎一切都在使用原始数据……或者对于大型阵列来说不可扩展。这是我当前的实现,可以改进并希望尽量避免标签。

 Test.prototype.unique = function (arr, artist, title, cb) {
        console.log(arr.length);
        var n, y, x, i, r;
        r = [];      
        o: for (i = 0, n = arr.length; i < n; i++) {

          for (x = 0, y = r.length; x < y; x++) {

                if (r[x].artist == arr[i].artist && r[x].title == arr[i].title) {
                    continue o;
                }
            }
            r.push(arr[i]);
        }

        cb(r);
    };

and the array looks something like this:

数组看起来像这样:

[{title: sky, artist: jon}, {title: rain, artist: Paul}, ....]

Order does not matter, but if sorting makes it more efficient then I am up for the challenge...

顺序无关紧要,但如果排序可以提高效率,那么我就可以接受挑战......

and for people who do not know o is a label and it is just saying jump back to the loop instead of pushing to the new array.

对于不知道 o 是标签的人,它只是说跳回循环而不是推送到新数组。

Pure javascript please no libs.

纯 javascript 请不要库。

ANSWERS SO FAR:

到目前为止的答案:

The Performance Test for the answers below: http://jsperf.com/remove-duplicates-for-loops

以下答案的性能测试:http: //jsperf.com/remove-duplicates-for-loops

回答by Henrique Feijo

I see, the problem there is that the complexity is squared. There is one trick to do it, it's simply by using "Associative arrays".

我明白了,问题在于复杂性是平方的。有一个技巧可以做到这一点,只需使用“关联数组”即可。

You can get the array, loop over it, and add the value of the array as a key to the associative array. Since it doesn't allow duplicated keys, you will automatically get rid of the duplicates.

您可以获取数组,对其进行循环,然后将数组的值作为键添加到关联数组中。由于它不允许重复的密钥,您将自动摆脱重复项。

Since you are looking for title and artist when comparing, you can actually try to use something like:

由于您在比较时正在寻找标题和艺术家,您实际上可以尝试使用以下内容:

var arrResult = {};
for (i = 0, n = arr.length; i < n; i++) {
    var item = arr[i];
    arrResult[ item.title + " - " + item.artist ] = item;
}

Then you just loop the arrResult again, and recreate the array.

然后您只需再次循环 arrResult,并重新创建数组。

var i = 0;
var nonDuplicatedArray = [];    
for(var item in arrResult) {
    nonDuplicatedArray[i++] = arrResult[item];
}

Updated to include Paul's comment. Thanks!

更新以包含保罗的评论。谢谢!

回答by Nico

Here is a solution that works for me.

这是一个对我有用的解决方案。

Helper functions:

辅助功能:

// sorts an array of objects according to one field
// call like this: sortObjArray(myArray, "name" );
// it will modify the input array
sortObjArray = function(arr, field) {
    arr.sort(
        function compare(a,b) {
            if (a[field] < b[field])
                return -1;
            if (a[field] > b[field])
                return 1;
            return 0;
        }
    );
}

// call like this: uniqueDishes = removeDuplicatesFromObjArray(dishes, "dishName");
// it will NOT modify the input array
// input array MUST be sorted by the same field (asc or desc doesn't matter)
removeDuplicatesFromObjArray = function(arr, field) {
    var u = [];
    arr.reduce(function (a, b) {
        if (a[field] !== b[field]) u.push(b);
        return b;
    }, []);
    return u;
}

and then simply call:

然后只需调用:

        sortObjArray(dishes, "name");
        dishes = removeDuplicatesFromObjArray(dishes, "name");

回答by Scott Mermelstein

Basic sort-then-unique implementation, fiddle HERE:

基本的排序然后唯一的实现,在这里小提琴:

function unique(arr) {
    var comparer = function compareObject(a, b) {
        if (a.title == b.title) {
            if (a.artist < b.artist) {
                return -1;
            } else if (a.artist > b.artist) {
                return 1;
            } else {
                return 0;
            }
        } else {
            if (a.title < b.title) {
                return -1;
            } else {
                return 1;
            }
        }
    }

    arr.sort(comparer);
    console.log("Sorted: " + JSON.stringify(arr));
    for (var i = 0; i < arr.length - 1; ++i) {
        if (comparer(arr[i], arr[i+1]) === 0) {
            arr.splice(i, 1);
            console.log("Splicing: " + JSON.stringify(arr));
        }
    }
    return arr;
}

It may or may not be the most efficient, and should be entirely scalable. I've added some console.logs so you can see it as it works.

它可能是也可能不是最有效的,并且应该是完全可扩展的。我添加了一些console.logs 以便您可以看到它的工作原理。

EDIT

编辑

In the interest of saving on the space the function used, I did that forloop at the end, but it seems likely that didn't properly find only unique results (depsite it passing my simple jsfiddle test). Please try replacing my forloop with the following:

为了节省函数使用的空间,我for在最后做了那个循环,但似乎没有正确找到唯一的结果(尽管它通过了我的简单 jsfiddle 测试)。请尝试用for以下内容替换我的循环:

var checker;
var uniqueResults = [];
for (var i = 0; i < arr.length; ++i) {
    if (!checker || comparer(checker, arr[i]) != 0) {
        checker = arr[i];
        uniqueResults.push(checker);
    }
}
return uniqueResults;

回答by user3303554

Below is Henrique Feijo's answer with ample explanation and an example that you can cut and paste:

下面是 Henrique Feijo 的回答,里面有充分的解释和一个你可以剪切和粘贴的例子:

Goal: Convert an array of objects that contains duplicate objects (like this one)...

目标:转换包含重复对象的对象数组(例如这个)...

[
    {
        "id": 10620,
        "name": "Things to Print"
    },
    {
        "id": 10620,
        "name": "Things to Print"
    },
    {
        "id": 4334,
        "name": "Interesting"
    }
]

... Into an array of objects without duplicate objects (like this one):

...进入一个没有重复对象的对象数组(像这个):

[
    {
        "id": 10620,
        "name": "Things to Print"
    },
    {
        "id": 4334,
        "name": "Interesting"
    }
]

Explanation provided in the comments:

评论中提供的解释:

    var allContent = [{
      "id": 10620,
      "name": "Things to Print"
    }, {
      "id": 10620,
      "name": "Things to Print"
    }, {
      "id": 4334,
      "name": "Interesting"
    }]

     //Put Objects Into As Associative Array. Each key consists of a composite value generated by each set of values from the objects in allContent.
    var noDupeObj = {} //Create an associative array. It will not accept duplicate keys.
    for (i = 0, n = allContent.length; i < n; i++) {
      var item = allContent[i]; //Store each object as a variable. This helps with clarity in the next line.
      noDupeObj[item.id + "|" + item.name] = item; //This is the critical step.
      //Here, you create an object within the associative array that has a key composed of the two values from the original object. 
      // Use a delimiter to not have foo+bar handled like fo+obar
      //Since the associative array will not allow duplicate keys, and the keys are determined by the content, then all duplicate content are removed. 
      //The value assigned to each key is the original object which is along for the ride and used to reconstruct the list in the next step.
    }

     //Recontructs the list with only the unique objects left in the doDupeObj associative array
    var i = 0;
    var nonDuplicatedArray = [];
    for (var item in noDupeObj) {
      nonDuplicatedArray[i++] = noDupeObj[item]; //Populate the array with the values from the noDupeObj.
    }

    console.log(nonDuplicatedArray)

回答by ShiningSandy

I use this function. its not doing any sorting, but produces result. Cant say about performance as never measure it.

我用这个功能。它不做任何排序,而是产生结果。不能说性能永远不会衡量它。

var unique = function(a){
    var seen = [], result = [];
    for(var len = a.length, i = len-1; i >= 0; i--){
        if(!seen[a[i]]){
            seen[a[i]] = true;
            result.push(a[i]);
        }
    }
    return result;
}

var ar = [1,2,3,1,1,1,1,1,"", "","","", "a", "b"]; console.log(unique(ar));// this will produce [1,2,3,"", "a", "b"] all unique elements.

var ar = [1,2,3,1,1,1,1,1,"", "","","", "a", "b"]; console.log(unique(ar));// 这将产生 [1,2,3,"", "a", "b"] 所有唯一元素。

回答by Raja Maragani

function remove_duplicates(objectsArray) {
    var arr = [], collection = []; 
    $.each(objectsArray, function (index, value) {
        if ($.inArray(value.id, arr) == -1) { 
            arr.push(value.id);
            collection.push(value);
        }
    });
    return collection;
}

回答by Abraham Hernandez

For those who love ES6 and short stuff, here it's one solution:

对于那些喜欢 ES6 和简短内容的人,这是一种解决方案:

const arr = [
  { title: "sky", artist: "Jon" },
  { title: "rain", artist: "Paul" },
  { title: "sky", artist: "Jon" }
];

Array.from(arr.reduce((a, o) => a.set(o.title, o), new Map()).values());

const arr = [
  { title: "sky", artist: "Jon" },
  { title: "rain", artist: "Paul" },
  { title: "sky", artist: "Jon" },
  { title: "rain", artist: "Jon" },
  { title: "cry", artist: "Jon" }
];

const unique = Array.from(arr.reduce((a, o) => a.set(o.title, o), new Map()).values());

console.log(`New array length: ${unique.length}`)

console.log(unique)

The above example only works for a unique titleor id. Basically, it creates a new map for songs with duplicate titles.

上面的示例仅适用于唯一的titleid. 基本上,它为具有重复标题的歌曲创建了一个新地图。

回答by sabzapple

Below code compares object with JSON as String format and removes duplicates and works fine with simple arrays.

下面的代码将对象与 JSON 作为字符串格式进行比较,并删除重复项,并且可以很好地处理简单数组。

    Array.prototype.unique=function(a){
     return function(){
        return this.filter(a)
     }
   }(
   function(a,b,c){
     var tmp=[]; 
     c.forEach(function(el){
        tmp.push(JSON.stringify(el))
    }); 
    return tmp.indexOf(JSON.stringify(a),b+1)<0
  })

回答by Mohammed Safeer

If you are using underscore js, it is easy to remove duplicate object. http://underscorejs.org/#uniq

如果您使用下划线 js,则很容易删除重复的对象。 http://underscorejs.org/#uniq