json - הסרת אובייקטים כפולים באמצעות Underscore עבור Javascript


יש לי את סוג המערך הזה:

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

אני רוצה לסנן את זה כדי שיהיה:

var bar = [ { "a" : "1" }, { "b" : "2" }];

ניסיתי להשתמש ב-_.uniq, אבל כנראה בגלל ש-{ "a" : "1" } לא שווה לעצמו, זה לא עובד. האם יש דרך לספק ל-underscore uniq פונקציית equals מותאמת?

תשובה #1

.uniq/.unique מקבל פונקציית קריאה חוזרת

var list = [{a:1,b:5},{a:1,c:5},{a:2},{a:3},{a:4},{a:3},{a:2}];

var uniqueList = _.uniq(list, function(item, key, a) { 
    return item.a;
});

// uniqueList = [Object {a=1, b=5}, Object {a=2}, Object {a=3}, Object {a=4}]

הערות :

  1. ערך ההחזרה של הקריאה חזרה שימש להשוואה
  2. החפץ הראשון להשוואה עם ערך החזרה ייחודי ששימש כייחודי
  3. underscorejs.org מציג שימוש ללא callback
  4. lodash.com מציג שימוש

דוגמה נוספת: שימוש בקריאה חוזרת כדי להוציא מותגי רכב וצבעים מרשימה

תשובה #2

אם אתה מחפש להסיר כפילויות על בסיס מזהה, תוכל לעשות משהו כזה:

var res = [
  {id: 1, content: 'heeey'},
  {id: 2, content: 'woah'}, 
  {id: 1, content:'foo'},
  {id: 1, content: 'heeey'},
];
var uniques = _.map(_.groupBy(res,function(doc){
  return doc.id;
}),function(grouped){
  return grouped[0];
});

//uniques
//[{id: 1, content: 'heeey'},{id: 2, content: 'woah'}]

תשובה #3

מימוש התשובה של Shiplu.

var foo = [ { "a" : "1" }, { "b" : "2" }, { "a" : "1" } ];

var x = _.uniq( _.collect( foo, function( x ){
    return JSON.stringify( x );
}));

console.log( x ); // returns [ { "a" : "1" }, { "b" : "2" } ]

תשובה #4

כאשר יש לי מזהה של תכונה, זו הדרך המועדפת עלי באנדרסקור:

var x = [{i:2}, {i:2, x:42}, {i:4}, {i:3}];
_.chain(x).indexBy("i").values().value();
// > [{i:2, x:42}, {i:4}, {i:3}]

תשובה #5

באמצעות הספרייה unique של underscore, הדברים הבאים עובדים עבורי, אני יוצר רשימה ייחודית על בסיס _id ואז מחזיר את הערך המחרוזתי של _id:

var uniqueEntities = _.uniq(entities, function (item, key, a) {
                                    return item._id.toString();
                                });

תשובה #6

הנה פתרון פשוט, המשתמש בהשוואת אובייקטים עמוקה כדי לבדוק כפילויות (ללא הצורך בהמרה ל-JSON, שהיא לא יעילה וגורמת לבעיות)

var newArr = _.filter(oldArr, function (element, index) {
    // tests if the element has a duplicate in the rest of the array
    for(index += 1; index < oldArr.length; index += 1) {
        if (_.isEqual(element, oldArr[index])) {
            return false;
        }
    }
    return true;
});

זה מסנן את כל האלמנטים אם יש להם כפילות מאוחר יותר במערך - כך שהאלמנט הכפול האחרון נשמר.

הבדיקה לחפיפה משתמשת ב-_.isEqual שמבצעת השוואה עמוקה מותאמת בין שני האובייקטים, עיין בתיעוד של isEqual של underscore למידע נוסף.

עריכה: עודכן לשימוש ב-_.filter שזה גישה נקייה יותר

תשובה #7

לתיעוד של lodash 4.6.1 יש את זה כדוגמה לשוויון מפתחות של אובייקטים:

_.uniqWith(objects, _.isEqual);

https://lodash.com/docs#uniqWith