जावास्क्रिप्ट में वस्तुओं की एक सरणी से डुप्लिकेट निकालें


373

मेरे पास एक ऑब्जेक्ट है जिसमें ऑब्जेक्ट की एक सरणी है।

things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

मैं सोच रहा हूँ कि किसी सरणी से डुप्लिकेट ऑब्जेक्ट को निकालने के लिए सबसे अच्छा तरीका क्या है। तो उदाहरण के लिए, चीजें। कुछ बन जाएगा ...

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}

क्या आपका मतलब है कि आप किसी हैशटेबल / ऑब्जेक्ट को एक ही सरणी में जोड़े जा रहे सभी समान मापदंडों से कैसे रोक सकते हैं?
मैथ्यू लॉक

1
मैथ्यू -> अगर किसी डुप्लिकेट ऑब्जेक्ट को पहली जगह में सरणी में जोड़ने से रोकने के लिए सरल है, तो इसे बाद में फ़िल्टर करने के बजाय, हाँ, यह ठीक भी होगा।
ट्रैविस

2
यह मुझे आश्चर्यचकित करता है कि लोग अपने चर नाम कैसे रखते हैं। कभी-कभी मुझे लगता है कि वे वास्तव में इसे अनावश्यक रूप से जटिल बनाना चाहते हैं। देखने के लिए अगला होगा aaaaa.aaaa.push(...):)
dazito

जवाबों:


154

एक आदिम विधि होगी:

var obj = {};

for ( var i=0, len=things.thing.length; i < len; i++ )
    obj[things.thing[i]['place']] = things.thing[i];

things.thing = new Array();
for ( var key in obj )
    things.thing.push(obj[key]);

15
आपको लूप के लिए कभी भी उपयोगकर्ता की लंबाई नहीं होनी चाहिए, क्योंकि यह हर पुनरावृत्ति पर गणना करके सब कुछ धीमा कर देगा। इसे लूप के बाहर एक वैरिएबल को असाइन करें और चीजों के बजाय वेरिएबल पास करें। कुछ भी।
0v3rth3d4wn 12

12
@aefxx मैं इस फ़ंक्शन को काफी नहीं समझता, आप इस स्थिति को कैसे संभालते हैं कि "स्थान" एक ही है लेकिन नाम अलग है, क्या इसे डुबकी माना जाना चाहिए या नहीं?
कुआँ

2
हालांकि यह काम करता है, यह सॉर्ट किए गए सरणी का ध्यान नहीं रखता है क्योंकि कुंजियों को लाने की गारंटी कभी नहीं होती है। तो, आप इसे फिर से छाँटना चाहते हैं। अब, मान लीजिए कि सरणी को क्रमबद्ध नहीं किया गया था लेकिन फिर भी इसका क्रम महत्वपूर्ण है, ऐसा कोई तरीका नहीं है जिससे आप यह सुनिश्चित कर सकें कि आदेश बरकरार रहेगा
दीपक जीएम

1
@DeepakGM तुम बिल्कुल सही हो। उत्तर (आवश्यक रूप से) किसी दिए गए आदेश को संरक्षित नहीं करेगा। यदि यह एक आवश्यकता है, तो किसी अन्य समाधान की तलाश करनी चाहिए।
एफीएक्सएक्स

एक्स को ऑब्जेक्ट से हटाने के लिए मैं ऊपर को कैसे संशोधित कर सकता हूं जिसमें एक्स के साथ-साथ डी-ड्यूड भी है?
रयान होल्टन

435

कैसे कुछ es6जादू के साथ ?

things.thing = things.thing.filter((thing, index, self) =>
  index === self.findIndex((t) => (
    t.place === thing.place && t.name === thing.name
  ))
)

संदर्भ URL

एक अधिक सामान्य समाधान होगा:

const uniqueArray = things.thing.filter((thing, index) => {
  const _thing = JSON.stringify(thing);
  return index === things.thing.findIndex(obj => {
    return JSON.stringify(obj) === _thing;
  });
});

स्टैकब्लिट्ज़ उदाहरण


81
इसे छोटा किया जा सकता है:things.thing = things.thing.filter((thing, index, self) => self.findIndex(t => t.place === thing.place && t.name === thing.name) === index)
जोश कोल

अच्छी तरह से काम! var अनूठे। });}); सुनिश्चित करें कि आप उचित JS वाक्यविन्यास का उपयोग करते हैं।
मोहम्मद सलेम लामिड़ी

वे उचित JS वाक्यविन्यास हैं। आपका उपयोग नहीं कर रहा है 1) वसा तीर फ़ंक्शन 2) अंतर्निहित वापसी या 3) डॉट नोटेशन। तुम्हारा ES5 सिंटेक्स है। अन्य ज्यादातर ES6 (ECMA2015) हैं। 2017 में सभी वैध हैं। जारेडविल्ली की टिप्पणी देखें।
agm1984

8
@vsync बस @ बीकेएम का उत्तर लें और इसे एक साथ रखें, एक सामान्य समाधान होगा: const uniqueArray = arrayOfObjects.filter((object,index) => index === arrayOfObjects.findIndex(obj => JSON.stringify(obj) === JSON.stringify(object))); jsfiddle.net/x9ku0p7L/28
Eydrian

9
यहां कुंजी यह है कि findIndex () विधि पहले तत्व का सूचकांक लौटाती है , इसलिए यदि कोई दूसरा तत्व मेल खाता है, तो यह फ़िल्टर के दौरान कभी नहीं मिलेगा और जोड़ा जाएगा। मैं इसे एक मिनट के लिए घूर रहा था :)
JBaczuk

111

यदि आप जावास्क्रिप्ट पुस्तकालयों जैसे अंडरस्कोर या लॉश का उपयोग कर सकते हैं , तो मैं _.uniqउनके पुस्तकालयों में कार्य को देखने की सलाह देता हूं । से lodash:

_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])

मूल रूप से, आप इस सरणी में पास होते हैं कि यहाँ एक ऑब्जेक्ट शाब्दिक है और आप इस विशेषता में पास होते हैं कि आप मूल डेटा सरणी में इस तरह से डुप्लिकेट को निकालना चाहते हैं:

var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name'); 

अद्यतन : अब लोडश ने एक .uniqByअच्छी तरह से पेश किया है ।


3
@ प्रवीण पैड: क्या मैंने कोड उदाहरण में अंडरस्कोर के बारे में कुछ कहा था? मैंने कहा कि 'लताड़' में यह कार्य है और अंडरस्कोर के समान हैं। मतदान से पहले, कृपया ध्यान से उत्तर पढ़ें।
अम्बोडी

// अद्वितीय वस्तुओं का उपयोग करता है _underscore.js HoldingObject = _.uniq (HoldingObject, function (आइटम, कुंजी, नाम) {return item.name;}) का उपयोग करके अद्वितीय वस्तुओं को सूचीबद्ध करता है।
प्रवीणपद

26
नोट: आपको अब uniqByइसके बजाय उपयोग करने की आवश्यकता है uniq, जैसे _.uniqBy(data, 'name')... प्रलेखन: lodash.com/docs#uniqBy
drmrbrewer

82

मुझे एक ही फ़ील्ड पर डुप्लिकेट के आधार पर, सरणी में डुप्लिकेट ऑब्जेक्ट को निकालने के लिए यह सटीक आवश्यकता थी। मुझे यहाँ कोड मिला: जावास्क्रिप्ट: ऑब्जेक्ट्स के एरे से डुप्लिकेट्स निकालें

इसलिए मेरे उदाहरण में, मैं किसी भी ऑब्जेक्ट को डुप्लिकेट लाइसेंसनाम स्ट्रिंग मान वाले सरणी से हटा रहा हूं।

var arrayWithDuplicates = [
    {"type":"LICENSE", "licenseNum": "12345", state:"NV"},
    {"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"OR"},
    {"type":"LICENSE", "licenseNum": "10849", state:"CA"},
    {"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];

function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));

परिणाम:

अद्वितीय है:

[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]

1
यह अधिक उपयोगी होगा यदि फ़ंक्शन 'मिथ्या ’वस्तुओं को भी फ़िल्टर कर सकता है। for(var i in array) { if(array[i][prop]){ //valid lookupObject[array[i][prop]] = array[i]; } else { console.log('falsy object'); } }
अब्दुल सादिक यालसिन

का उपयोग करके जटिलता 0 (n) को नीचे क्यों नहीं लाया जाए: for (let i in originalArray) { if (lookupObject[originalArray[i]['id']] === undefined) { newArray.push(originalArray[i]); } lookupObject[originalArray[i]['id']] = originalArray[i]; }
ट्यूडर बी

यह सबसे अच्छा तरीका है क्योंकि यह जानना महत्वपूर्ण है कि यह क्या है कि आप डुप्लिकेट नहीं होना चाहते हैं। अब यह e6 मानकों के लिए reducer के माध्यम से किया जा सकता है?
क्रिश्चियन मैथ्यू

69

ES6 + के लिए सबसे छोटा एक लाइनर

idएक सरणी में अद्वितीय खोजें ।

arr.filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i)

कई गुणों द्वारा अद्वितीय ( placeऔर name)

arr.filter((v,i,a)=>a.findIndex(t=>(t.place === v.place && t.name===v.name))===i)

सभी गुणों द्वारा अद्वितीय (यह बड़े सरणियों के लिए धीमा होगा)

arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)

अंतिम घटना रखें।

arr.slice().reverse().filter((v,i,a)=>a.findIndex(t=>(t.id === v.id))===i).reverse()

2
मैजिक, यह सही जवाब है
लुइस कॉन्ट्रेरास

48

सेट का उपयोग कर एक लाइनर

var things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

// assign things.thing to myData for brevity
var myData = things.thing;

things.thing = Array.from(new Set(myData.map(JSON.stringify))).map(JSON.parse);

console.log(things.thing)

स्पष्टीकरण:

  1. new Set(myData.map(JSON.stringify))स्ट्रिंग myData तत्वों का उपयोग करके एक सेट ऑब्जेक्ट बनाता है ।
  2. सेट ऑब्जेक्ट यह सुनिश्चित करेगा कि प्रत्येक तत्व अद्वितीय है।
  3. फिर मैं Array.from का उपयोग करके बनाए गए सेट के तत्वों के आधार पर एक सरणी बनाता हूं।
  4. अंत में, मैं JSON.parse का उपयोग कड़े तत्व को एक वस्तु में बदलने के लिए करता हूं।

18
यह समस्या {a: 1, b: 2} के बराबर नहीं होगी {b: 2, a: 1}
PirateApp

2
ध्यान रखें कि दिनांक गुणों के साथ कोई समस्या नहीं होगी
MarkosyanArtur

यह पंक्ति एक पंक्ति वस्तु के साथ यादृच्छिक अशक्त मान बनाती है जो वस्तुओं के मूल सरणी में मौजूद नहीं है। क्या आप मदद कर सकते हैं?
B1K

46

ES6 + का उपयोग करके एक ही पंक्ति में आप कुंजी द्वारा वस्तुओं की एक अद्वितीय सूची प्राप्त कर सकते हैं:

const unique = [...new Map(arr.map(item => [item[key], item])).values()]

इसे एक फंक्शन में रखा जा सकता है:

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

यहाँ एक काम कर उदाहरण है:

const arr = [
    {place: "here",  name: "x", other: "other stuff1" },
    {place: "there", name: "x", other: "other stuff2" },
    {place: "here",  name: "y", other: "other stuff4" },
    {place: "here",  name: "z", other: "other stuff5" }
]

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

const arr1 = getUniqueListBy(arr, 'place')

console.log("Unique by place")
console.log(JSON.stringify(arr1))

console.log("\nUnique by name")
const arr2 = getUniqueListBy(arr, 'name')

console.log(JSON.stringify(arr2))

यह कैसे काम करता है

पहले एरे को रीमेक किया जाता है, इसे मैप के इनपुट के रूप में इस्तेमाल किया जा सकता है

arr.map (आइटम => [आइटम [कुंजी], आइटम]);

जिसका अर्थ है कि सरणी का प्रत्येक आइटम 2 तत्वों के साथ दूसरे सरणी में बदल जाएगा; प्रथम तत्व के रूप में चयनित कुंजी और दूसरे तत्व के रूप में संपूर्ण प्रारंभिक वस्तु , इसे प्रविष्टि कहा जाता है (उदाहरण सरणी प्रविष्टियाँ , मानचित्र प्रविष्टियाँ )। और यहां एक उदाहरण है जिसमें मानचित्र निर्माण में सरणी प्रविष्टियों को जोड़ने का एक उदाहरण दिखाया गया है।

उदाहरण जब कुंजी जगह है :

[["here", {place: "here",  name: "x", other: "other stuff1" }], ...]

दूसरे, हम इस संशोधित सरणी को मैप कंस्ट्रक्टर के पास भेजते हैं और यहाँ जादू हो रहा है। मानचित्र डुप्लिकेट कुंजी मूल्यों को समाप्त कर देगा, केवल उसी कुंजी के अंतिम सम्मिलित मूल्य को रखेगा। नोट : मानचित्र प्रविष्टि का क्रम रखता है। ( मानचित्र और वस्तु के बीच अंतर की जाँच करें )

नया नक्शा (प्रवेश सरणी ऊपर मैप किया गया)

तीसरा हम मूल वस्तुओं को पुनः प्राप्त करने के लिए मानचित्र मानों का उपयोग करते हैं, लेकिन इस बार बिना डुप्लिकेट के।

नया नक्शा (मैप किया गया) .values ​​()

और पिछले एक को उन मूल्यों को एक नए नए सरणी में जोड़ना है ताकि यह प्रारंभिक संरचना के रूप में दिख सके और वापस आ जाए:

वापसी [... नया मानचित्र (mappedArr) .values ​​()]


यह मूल प्रश्न का उत्तर नहीं देता है क्योंकि यह एक खोज है id। प्रश्न को सभी क्षेत्रों में अद्वितीय होने की आवश्यकता है जैसे कि placeऔरname
एल। होलांडा

आपका ES6 फ़ंक्शन बहुत संक्षिप्त और व्यावहारिक लगता है। क्या आप इसे थोड़ा और समझा सकते हैं? वास्तव में क्या हो रहा है? क्या पहले या अंतिम डुप्लिकेट हटा दिए गए हैं? या यह यादृच्छिक है, जो डुप्लिकेट हटा दिया जाता है? यह उपयोगी होगा, धन्यवाद।
डेविड शुमान

जहाँ तक मैं बता सकता हूँ, कुंजी के रूप में संपत्ति के मूल्य वाला एक मानचित्र बनाया जाता है। लेकिन यह 100% नहीं है कि कैसे या यदि सरणी का क्रम संरक्षित है।
डेविड शुमान

1
हाय @DavidSchumann, मैं जवाब को अपडेट करूंगा और बताऊंगा कि यह कैसे काम करता है। लेकिन संक्षिप्त जवाब के लिए आदेश संरक्षित है और पहले वाले को हटा दिया जाता है ... बस यह सोचें कि यह नक्शे में कैसे डाला जाता है ... यह जांचता है कि क्या कुंजी पहले से मौजूद है, इसे अपडेट करेगा, इसके बाद अंतिम एक ही रहेगा
वी । साम्बोर

30

यदि आपको किसी ऑब्जेक्ट के केवल एक क्षेत्र से तुलना की आवश्यकता है, तो एरियर पुनरावृत्ति विधियों का उपयोग करते हुए यह करने के लिए एक और विकल्प है:

    function uniq(a, param){
        return a.filter(function(item, pos, array){
            return array.map(function(mapItem){ return mapItem[param]; }).indexOf(item[param]) === pos;
        })
    }

    uniq(things.thing, 'place');

हालाँकि इसमें O (n²) से बड़ा ऑर्डर है, यह मेरे उपयोग के मामले में फिट बैठता है क्योंकि मेरी सरणी का आकार हमेशा 30 से कम रहेगा। धन्यवाद!
स्टीरियो जूल

24

एक लाइनर यहाँ है

let arr = [
  {id:1,name:"sravan ganji"},
  {id:2,name:"anu"},
  {id:4,name:"mammu"},
  {id:3,name:"sanju"},
  {id:3,name:"ram"},
];

console.log(Object.values(arr.reduce((acc,cur)=>Object.assign(acc,{[cur.id]:cur}),{})))


1
यदि आप केवल एक ही डुप्लिकेट वैल्यू वाली वस्तुओं को हटाना चाहते हैं तो अच्छा और साफ है, पूरी तरह से डुप्लिकेट ऑब्जेक्ट्स के लिए इतना साफ नहीं है।
डेविड बार्कर

22

यदि आप सभी परिवर्धन के बाद तक डुप्लिकेट को खत्म करने के लिए इंतजार कर सकते हैं, तो विशिष्ट दृष्टिकोण पहले सरणी को सॉर्ट करना है और फिर डुप्लिकेट को समाप्त करना है। सॉर्टिंग प्रत्येक तत्व के लिए सरणी को स्कैन करने के एन * एन दृष्टिकोण से बचती है क्योंकि आप उनके माध्यम से चलते हैं।

"डुप्लिकेट को निकाल" समारोह आमतौर पर कहा जाता है अद्वितीय या uniq । कुछ मौजूदा कार्यान्वयन दो चरणों को जोड़ सकते हैं, उदाहरण के लिए, प्रोटोटाइप का यूनीक

यदि आपके पुस्तकालय में पहले से कोई नहीं है, तो इस पोस्ट में कुछ विचार हैं (और कुछ को टालने के लिए :-)) ! व्यक्तिगत रूप से मुझे यह सबसे सीधा लगता है:

    function unique(a){
        a.sort();
        for(var i = 1; i < a.length; ){
            if(a[i-1] == a[i]){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }  

    // Provide your own comparison
    function unique(a, compareFunc){
        a.sort( compareFunc );
        for(var i = 1; i < a.length; ){
            if( compareFunc(a[i-1], a[i]) === 0){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }

यह एक प्राकृतिक क्रम के बिना सामान्य वस्तुओं के लिए काम नहीं करेगा।
टिम डाउन

सच है, मैंने एक उपयोगकर्ता-आपूर्ति की तुलना संस्करण जोड़ा है।
मैक्कुल्ट

आपके उपयोगकर्ता द्वारा दिया गया तुलनात्मक संस्करण काम नहीं करेगा क्योंकि यदि आपका तुलनात्मक कार्य है function(_a,_b){return _a.a===_b.a && _a.b===_b.b;}तो सरणी को क्रमबद्ध नहीं किया जाएगा।
graham.reeds

1
यह एक अमान्य तुलना फ़ंक्शन है। से developer.mozilla.org/en/Core_JavaScript_1.5_Reference/... ... समारोह की तुलना (ए, बी) {अगर (एक कुछ आदेश कसौटी द्वारा ख से कम है) वापसी -1; यदि (a, ऑर्डरिंग मानदंड से b से अधिक है) रिटर्न 1; // बी रिटर्न 0 के बराबर होना चाहिए; } ...
maccullt

22

सबसे सरल तरीका उपयोग है filter:

var uniq = {}
var arr  = [{"id":"1"},{"id":"1"},{"id":"2"}]
var arrFiltered = arr.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));
console.log('arrFiltered', arrFiltered)


6
यह स्टैक ओवरफ्लो पर एक अच्छा अभ्यास है ताकि यह समझा जाए कि आपके समाधान को क्यों काम करना चाहिए, विशेष रूप से आपका अन्य उत्तरों से बेहतर कैसे है। अधिक जानकारी के लिए उत्तर कैसे पढ़ें ।
शमूएल ल्यू

यह मूल प्रश्न का उत्तर नहीं देता है क्योंकि यह एक खोज है id। प्रश्न को सभी क्षेत्रों में अद्वितीय होने की आवश्यकता है जैसेplacename
एल। होलांडा

16

यह ऐसा करने का एक सामान्य तरीका है: आप एक फ़ंक्शन में पास होते हैं जो परीक्षण करता है कि किसी सरणी के दो तत्वों को समान माना जाता है या नहीं। इस मामले में, यह दो वस्तुओं के मूल्यों nameऔर placeगुणों की तुलना करता है।

ES5 उत्तर

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arr.some(function(item) { return equals(item, val); })) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

var things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

removeDuplicates(things, thingsEqual);
console.log(things);

मूल ES3 उत्तर

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if ( equals(arr[i], val) ) {
            return true;
        }
    }
    return false;
}

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

removeDuplicates(things.thing, thingsEqual);

1
दो वस्तुएं समान मूल्यांकन नहीं करेंगी, भले ही वे समान गुणों और मूल्यों को साझा करें।
kennebec

हाँ मैं जानता हूँ। लेकिन उचित बिंदु, मैं प्रश्न को सही ढंग से पढ़ने में विफल रहा हूं: मैंने यह नहीं देखा था कि यह समान गुणों वाली वस्तुएं थीं जो उन्हें बाहर निकालने की जरूरत थी। मैं अपना उत्तर संपादित करूँगा।
टिम डाउन

1
सरणी के अंदर रहते हुए के बजाय- Array.prototype..some पद्धति का उपयोग करें यदि सरणी सदस्यों में से एक मैच की स्थिति से सच हो जाता है
MarkosyanArtur

13

सूची में एक और जोड़ने के लिए। ES6 और के Array.reduceसाथ का उपयोग करना Array.find
इस उदाहरण में एक guidसंपत्ति के आधार पर वस्तुओं को फ़िल्टर करना ।

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

एक संपत्ति के चयन की अनुमति देने और इसे एक लाइनर में संपीड़ित करने के लिए इसका विस्तार करना:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

इसका उपयोग करने के लिए वस्तुओं की एक सरणी और एक स्ट्रिंग मान के रूप में उस कुंजी का नाम जिसे आप डु-ड्यू करना चाहते हैं:

const result = uniqify(myArrayOfObjects, 'guid')

11

तुम भी एक का उपयोग कर सकते हैं Map:

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

पूर्ण नमूना:

const things = new Object();

things.thing = new Array();

things.thing.push({place:"here",name:"stuff"});
things.thing.push({place:"there",name:"morestuff"});
things.thing.push({place:"there",name:"morestuff"});

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));

परिणाम:

[
    {
        "place": "here",
        "name": "stuff"
    },
    {
        "place": "there",
        "name": "morestuff"
    }
]

+1, अच्छा थोडा समझाकर कहा जाता है कि डुप्लिकेटिंग का आंतरिक कार्य अच्छा होगा - उज्ज्वल पक्ष पर मैं अब कम करना समझता हूं: D
MimiEAM

11

डांग, बच्चों, चलो इस बात को नीचे कुचल दें, हम क्यों नहीं?

let uniqIds = {}, source = [{id:'a'},{id:'b'},{id:'c'},{id:'b'},{id:'a'},{id:'d'}];
let filtered = source.filter(obj => !uniqIds[obj.id] && (uniqIds[obj.id] = true));
console.log(filtered);
// EXPECTED: [{id:'a'},{id:'b'},{id:'c'},{id:'d'}];


यह मूल प्रश्न का उत्तर नहीं देता है क्योंकि यह एक खोज है id। प्रश्न को सभी क्षेत्रों में अद्वितीय होने की आवश्यकता है जैसे कि placeऔरname
एल। होलांडा

यह समस्या के उपरोक्त सामान्यीकरण का परिशोधन है। मूल प्रश्न 9 साल पहले पोस्ट किया गया था, इसलिए मूल पोस्टर शायद placeऔर nameआज के बारे में चिंतित नहीं है। इस धागे को पढ़ने वाला कोई भी व्यक्ति वस्तुओं की सूची को प्राप्त करने का एक इष्टतम तरीका ढूंढ रहा है, और यह ऐसा करने का एक कॉम्पैक्ट तरीका है।
क्लिफ हॉल

11

एक टाइपस्क्रिप्ट समाधान

यह डुप्लिकेट ऑब्जेक्ट को हटा देगा और ऑब्जेक्ट के प्रकारों को भी संरक्षित करेगा।

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}

2
यह बहुत अच्छा और छोटा है!
मोज़ज

और सुपर स्लो भी ...
एल। होलांडा

7

मानते हुए lodash.uniqWith

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];

_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]

उत्तम ! धन्यवाद ;-)
डॉनफैबियोलाज़

1
न तो लंकेश के अंकल ने और न ही अंकल ने कोई चाल चली, लेकिन तुम्हारा समाधान किया। धन्यवाद! कृपया अपने कोड का स्रोत दें, यदि यह एक सीधी प्रति है। lodash.com/docs/4.17.10#uniqWith
मनु CJ

5

एक अन्य विकल्प एक कस्टम इंडेक्सऑफ फ़ंक्शन बनाना होगा, जो प्रत्येक वस्तु के लिए आपकी चुनी हुई संपत्ति के मूल्यों की तुलना करता है और इसे कम फ़ंक्शन में लपेटता है।

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);

इसने मेरे लिए बहुत अच्छा काम किया - मैंने इसे lodash.isequalnpm पैकेज के साथ जोड़ा एक लाइटवेट ऑब्जेक्ट तुलनित्र के रूप में, जो यूनिक ऐरे फ़िल्टरिंग कर रहा है ... उदाहरण के लिए ऑब्जेक्ट्स के अलग-अलग ऐरे। if (_.isEqual(a[i], b)) {एक एकल संपत्ति
स्लीवरनिंजा - MSFT

5

let myData = [{place:"here",name:"stuff"}, 
 {place:"there",name:"morestuff"},
 {place:"there",name:"morestuff"}];


let q = [...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

console.log(q)

ES6 और का उपयोग कर एक-लाइनर new Map()

// assign things.thing to myData
let myData = things.thing;

[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

विवरण:-

  1. .map()डेटा सूची पर करना और प्रत्येक व्यक्ति ऑब्जेक्ट को एक [key, value]जोड़ी सरणी (लंबाई = 2) में परिवर्तित करना , पहला तत्व (कुंजी) stringifiedऑब्जेक्ट का संस्करण होगा और दूसरा (मान) एक होगाobject ही होगा।
  2. ऊपर बनाई गई सरणी सूची में जोड़ने के new Map()लिए कुंजी के रूप में होगाstringifiedऑब्जेक्ट के ऑब्जेक्ट के और किसी भी समान कुंजी के परिणामस्वरूप पहले से मौजूद कुंजी को ओवरराइड करना होगा।
  3. .values()मैप में सभी मानों के साथ MapIterator का उपयोग करना होगा (obj हमारे मामले में)
  4. अंत में, spread ...ऑपरेटर उपरोक्त चरण से मानों के साथ नया एरियर देने के लिए।

4

यहां es6 के लिए एक समाधान है जहां आप केवल अंतिम आइटम रखना चाहते हैं। यह समाधान कार्यात्मक है और Airbnb शैली अनुरूप है।

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]

आप डुप्लिकेट निकाल सकते हैं और आप इस कोड के साथ सभी डुप्लिकेट भी निकाल सकते हैं। नाइस
sg28

4

removeDuplicates () ऑब्जेक्ट की एक सरणी में लेता है और किसी भी डुप्लिकेट ऑब्जेक्ट (आईडी प्रॉपर्टी के आधार पर) के बिना एक नया एरे देता है।

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);

अनुमानित परिणाम:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];

सबसे पहले, हम चर uniq का मान किसी खाली वस्तु पर सेट करते हैं।

अगला, हम वस्तुओं की सरणी के माध्यम से फ़िल्टर करते हैं। फ़िल्टर सभी तत्वों के साथ एक नया सरणी बनाता है जो प्रदान किए गए फ़ंक्शन द्वारा कार्यान्वित परीक्षण को पास करता है।

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));

ऊपर, हम && की लघु-संचलन कार्यक्षमता का उपयोग करते हैं। यदि && के बाईं ओर स्थित सही का मूल्यांकन करता है, तो वह && के दाईं ओर का मान लौटाता है। यदि बाईं ओर गलत है, तो यह वापस वही होता है जो && के बाईं ओर है।

प्रत्येक ऑब्जेक्ट (obj) के लिए, हम obj.id के मान नामक एक संपत्ति के लिए uniq की जांच करते हैं (इस मामले में, पहली पुनरावृत्ति पर यह संपत्ति '1' के लिए जांच करेगा।) हम इसके विपरीत चाहते हैं कि यह (या तो सच है) या गलत) जिसके कारण हम इसका उपयोग करते हैं! in; uniq [obj.id]। अगर uniq के पास पहले से ही id प्रॉपर्टी है, तो यह सही है जो फ़िल्टर का कार्य करता है (!) फ़िल्टर फ़ंक्शन को उस obj को जोड़ने के लिए नहीं कहता है। हालाँकि, यदि उसे obj.id संपत्ति नहीं मिलती है, तो वह झूठी हो जाती है जो तब सही (!) का मूल्यांकन करती है और सब कुछ वापस & nbsp; या (uniq [obj.id] = true) के अधिकार में वापस कर देती है। यह एक सत्य मान है, फ़िल्टर विधि को उस ओबज को लौटे हुए सरणी में जोड़ने के लिए, और यह भी संपत्ति {1: true} को uniq में जोड़ता है। यह सुनिश्चित करता है कि उसी आईडी के साथ किसी भी अन्य उदाहरण को फिर से नहीं जोड़ा जाएगा।


शायद अपने कोड की व्याख्या करें, और यह प्रश्न का उत्तर कैसे देता है?
मिश्रण 3 डी

धन्यवाद, मिक्स ३ डी। मैंने स्पष्टीकरण जोड़ा।
MarkN

यह समझाने के लिए धन्यवाद! यह समाधान मेरे लिए काम करता है, और यहां तैनात अन्य लोगों के एक जोड़े के समान है, हालांकि मुझे समझ नहीं आया कि क्या हो रहा था :)
टिम मोलियार

3
let data = [
  {
    'name': 'Amir',
    'surname': 'Rahnama'
  }, 
  {
    'name': 'Amir',
    'surname': 'Stevens'
  }
];
let non_duplicated_data = _.uniqBy(data, 'name');

9
कृपया अपने कोड के आसपास एक स्पष्टीकरण जोड़ें ताकि भविष्य के आगंतुक समझ सकें कि यह आप क्या कर रहे हैं। धन्यवाद।
बग्स

आपका जवाब बाहरी कोड लाइब्रेरी पर निर्भर है ...
टेलर ए। लीच

3

मेरा मानना ​​है कि वस्तुओं के reduceसाथ पूरी तरह से तुलना JSON.stringifyकरने और चुनिंदा लोगों को जोड़ने के लिए जो पहले से ही संचायक में नहीं हैं, एक सुरुचिपूर्ण तरीका है।

ध्यान रखें कि JSON.stringifyचरम मामलों में एक प्रदर्शन मुद्दा बन सकता है जहां सरणी में कई ऑब्जेक्ट हैं और वे जटिल हैं, लेकिन अधिकांश समय के लिए , यह IMHO जाने का सबसे छोटा तरीका है।

var collection= [{a:1},{a:2},{a:1},{a:3}]

var filtered = collection.reduce((filtered, item) => {
  if( !filtered.some(filteredItem => JSON.stringify(filteredItem) == JSON.stringify(item)) )
    filtered.push(item)
  return filtered
}, [])

console.log(filtered)

उसी लिखने का एक और तरीका (लेकिन कम कुशल):

collection.reduce((filtered, item) => 
  filtered.some(filteredItem => 
    JSON.stringify(filteredItem ) == JSON.stringify(item)) 
      ? filtered
      : [...filtered, item]
, [])

वह जो मेरे लिए काम करता है! धन्यवाद!
javascript110899

2

वस्तुओं के सरणी से डुप्लिकेट को हटाने के ईएस 6 तरीकों की खोज जारी रखना: एक सभ्य विकल्प प्रदान करने thisArgके Array.prototype.filterलिए तर्क स्थापित करना new Set:

const things = [
  {place:"here",name:"stuff"},
  {place:"there",name:"morestuff"},
  {place:"there",name:"morestuff"}
];

const filtered = things.filter(function({place, name}) {

  const key =`${place}${name}`;

  return !this.has(key) && this.add(key);

}, new Set);

console.log(filtered);

हालांकि, यह तीर के कार्यों के साथ काम नहीं करेगा () =>, जैसा thisकि उनके शाब्दिक दायरे के लिए बाध्य है।


2

एक पंक्ति में es6 जादू ... उस पर पठनीय!

// returns the union of two arrays where duplicate objects with the same 'prop' are removed
const removeDuplicatesWith = (a, b, prop) => a.filter(x => !b.find(y => x[prop] === y[prop]);

2

ईएस 6 'कम ’और' फाइंड हेल्पर’ विधियों के साथ सरल समाधान

कुशलता से और पूरी तरह से ठीक काम करता है!

"use strict";

var things = new Object();
things.thing = new Array();
things.thing.push({
    place: "here",
    name: "stuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});
things.thing.push({
    place: "there",
    name: "morestuff"
});

// the logic is here

function removeDup(something) {
    return something.thing.reduce(function (prev, ele) {
        var found = prev.find(function (fele) {
            return ele.place === fele.place && ele.name === fele.name;
        });
        if (!found) {
            prev.push(ele);
        }
        return prev;
    }, []);
}
console.log(removeDup(things));

इससे मुझे बहुत मदद मिली, धन्यवाद
jpisty

1

यदि आपको अपने अनोखे सरणी को बाद में क्रमबद्ध करने में कोई आपत्ति नहीं है, तो यह एक कुशल समाधान होगा:

things.thing
  .sort(((a, b) => a.place < b.place)
  .filter((current, index, array) =>
    index === 0 || current.place !== array[index - 1].place)

इस तरह, आपको केवल सरणी में पिछले तत्व के साथ वर्तमान तत्व की तुलना करनी होगी। फ़िल्टर करने से पहले एक बार छंटनी ( O(n*log(n))) हर सरणी तत्व के लिए पूरे सरणी में डुप्लिकेट की तुलना में सस्ती है ( O(n²))।


1

यह सरल तरीका है कि वस्तुओं की सरणी से दोहराव को कैसे हटाया जाए।

मैं डेटा के साथ बहुत काम करता हूं और यह मेरे लिए उपयोगी है।

const data = [{name: 'AAA'}, {name: 'AAA'}, {name: 'BBB'}, {name: 'AAA'}];
function removeDuplicity(datas){
    return datas.filter((item, index,arr)=>{
    const c = arr.map(item=> item.name);
    return  index === c.indexOf(item.name)
  })
}

console.log(removeDuplicity(data))

कंसोल में प्रिंट होगा:

[[object Object] {
name: "AAA"
}, [object Object] {
name: "BBB"
}]

इस समाधान को स्थिर सरणी से दोहराव को हटाने के लिए डिज़ाइन किया गया है, लेकिन जब यू बैकेंड से डेटा को डेटा सरणी में धकेलते हैं तो प्रतिस्थापित का उपयोग करने पर विचार करें। क्योंकि इस स्थिति में डेटा सरणी में धकेल दिया गया नया मान हटा दिया जाएगा और "पुराना" मान अभी भी डेटा सरणी में संग्रहीत किया जाएगा।
जुराज

1
str =[
{"item_id":1},
{"item_id":2},
{"item_id":2}
]

obj =[]
for (x in str){
    if(check(str[x].item_id)){
        obj.push(str[x])
    }   
}
function check(id){
    flag=0
    for (y in obj){
        if(obj[y].item_id === id){
            flag =1
        }
    }
    if(flag ==0) return true
    else return false

}
console.log(obj)

str ऑब्जेक्ट्स की एक सरणी है। समान मूल्य वाली वस्तुएं मौजूद हैं (यहां एक छोटा उदाहरण, दो आइटम हैं जिनका समान item_id 2 है)। check (id) एक ऐसा फंक्शन है जो यह जांचता है कि क्या किसी वस्तु में समान item_id मौजूद है या नहीं। अगर यह मौजूद है तो झूठे वापस आ जाएं अन्यथा सही लौटें। उस परिणाम के अनुसार, ऑब्जेक्ट को एक नए सरणी obj में धकेलें । उपरोक्त कोड का आउटपुट है [{"item_id":1},{"item_id":2}]


कुछ विवरण जोड़ें
मैथ्यू सनी

@ बिल्ला क्या यह ठीक है?
बीबिन जैमोन

1

क्या आपने लोदश पुस्तकालय के बारे में सुना है? मैं आपको इस उपयोगिता की सलाह देता हूं, जब आप वास्तव में अपने तर्क को कोड पर लागू नहीं करना चाहते हैं, और पहले से मौजूद कोड का उपयोग करें जो कि अनुकूलित और विश्वसनीय है।

इस तरह एक सरणी बनाने पर विचार करें

things.thing.push({place:"utopia",name:"unicorn"});
things.thing.push({place:"jade_palace",name:"po"});
things.thing.push({place:"jade_palace",name:"tigress"});
things.thing.push({place:"utopia",name:"flying_reindeer"});
things.thing.push({place:"panda_village",name:"po"});

ध्यान दें कि यदि आप किसी एक विशेषता को अद्वितीय रखना चाहते हैं, तो आप लॉश लाइब्रेरी का उपयोग करके बहुत अच्छा कर सकते हैं। यहां, आप _.uniqBy का उपयोग कर सकते हैं

.uniqBy (सरणी, [iteratee = .identity])

यह तरीका _.uniq की तरह है (जो किसी सरणी के डुप्लिकेट-मुक्त संस्करण को लौटाता है, जिसमें प्रत्येक तत्व की केवल पहली घटना को रखा जाता है) सिवाय इसके कि वह पुनरावृति स्वीकार करता है, जो मानदंड बनाने के लिए सरणी में प्रत्येक तत्व के लिए लागू किया जाता है जिसके द्वारा विशिष्टता की गणना की जाती है।

इसलिए, उदाहरण के लिए, यदि आप 'एरे' की विशिष्ट विशेषता वाले ऐरे को वापस करना चाहते हैं

_.unqBy (चीजें। कुछ भी, 'जगह')

इसी तरह, यदि आप 'नाम' के रूप में अद्वितीय विशेषता चाहते हैं

_.uniqBy (चीजें। कुछ भी, 'नाम')

उम्मीद है की यह मदद करेगा।

चीयर्स!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.