वस्तुओं को जोड़ना (सहयोगी सरणियाँ)


147

जावास्क्रिप्ट में दो साहचर्य सरणियों के विलय का सबसे अच्छा / मानक तरीका क्या है? क्या हर कोई सिर्फ अपना forलूप रोल करके ऐसा करता है ?


10
जावास्क्रिप्ट btw में कोई साहचर्य सरणियाँ हैं, केवल वस्तुओं।
gblazex

पर्ल में CrossRef वही सवाल: stackoverflow.com/questions/350018/...
dreftymac

जावास्क्रिप्ट में सहयोगी सरणियाँ: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
क्रिस मार्टिन

जवाबों:


204

jquery के साथ आप कॉल कर सकते हैं $.extend

var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};

var obj3 = $.extend(obj1, obj2); 

obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS

(assoc। सरणियाँ js में ऑब्जेक्ट हैं)

यहाँ देखें : http://api.jquery.com/jQuery.extend/


संपादित करें: जैसे rymo ने सुझाव दिया है, यह इस तरह से करना बेहतर है:

obj3 = $.extend({}, obj1, obj2); 
obj3 == {a: 4, b: 2, c: 110}

यहाँ के रूप में obj1 (और obj2) अपरिवर्तित रहते हैं।


edit2: 2018 में इसे करने का तरीका Object.assignनिम्न है:

var obj3 = Object.assign({}, obj1, obj2); 
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS

ES6 के साथ काम करने पर यह स्प्रेड ऑपरेटर के साथ प्राप्त किया जा सकता है :

const obj3 = { ...obj1, ...obj2 };

54
या obj1$.extend({}, obj1, obj2)
मैकिंग

हां, जब संदर्भों द्वारा पारित क्लोजर और ऑब्जेक्ट्स के साथ काम करते हैं, तो बाद के संचालन के लिए मूल वस्तु को प्रभावित करने से बचने के लिए राइमो की सलाह लें।
नाथन स्मिथ

2
आधुनिक ब्राउज़रों के लिए, @manfred का उपयोग करके समाधान की जाँच करें Object.assign(), जो कि JQuery पर निर्भर नहीं करता है यदि आप पहले से ही पुस्तकालय का उपयोग नहीं कर रहे हैं।
फिल

यह काम करता है, लेकिन यह पहले पैरामीटर को बदल देता है और यह कुछ ऐसा है जिसके बारे में आपको जानकारी होनी चाहिए। Developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
kulpae

62

अब 2016 में मैं कहूंगा कि सबसे अच्छा / मानक तरीका Object.assign ()
शुद्ध जावास्क्रिप्ट है। कोई jQuery की जरूरत है।

obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2);  // Object {a: 4, b: 2, c: 110}

अधिक जानकारी, उदाहरण और पॉलीफ़िल यहां:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


Obj3 के लिए प्रकार क्या है? क्या होगा अगर obj1 प्रकार IABC है, तो क्या obj3 उस प्रकार को बाद में रखेगा?
हवामाहाओ

49

इस प्रकार यह प्रोटोटाइप करता है:

Object.extend = function(destination, source) {
    for (var property in source) {
        if (source.hasOwnProperty(property)) {
            destination[property] = source[property];
        }
    }
    return destination;
};

उदाहरण के लिए कहा जाता है:

var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };

var shortnames = Object.extend(arr1,arr2);

संपादित करें : hasOwnProperty () की जाँच करें जैसा कि टिप्पणियों में bucabay द्वारा सही ढंग से बताया गया है


6
यह सुनिश्चित करने के लिए कि आपको केवल तत्काल गुणों की प्रतिलिपि बनाना है, आपको परीक्षण स्रोत .hasOwnProperty (संपत्ति) की आवश्यकता होगी। जैसा कि यह है, यह Object.prototype
bucabay

22

इसे सरल रखें...

function mergeArray(array1,array2) {
  for(item in array1) {
    array2[item] = array1[item];
  }
  return array2;
}

6
आप किसी भी गुण की नकल करने से बचने के लिए hasOwnProperty की जाँच करेंarrau1.prototype
LeeGee

@LeeGee सही है। आपको उस hasOwnPropertyजाँच की आवश्यकता है । ऑब्जेक्ट को सरणियों के रूप में संदर्भित करना भी भ्रामक है (वे ऑब्जेक्ट्स हैं), arg नामों को यह बताना चाहिए कि array2 उत्परिवर्तित है या एक नई वस्तु वापस आनी चाहिए। मैं उत्तर को संपादित करूंगा लेकिन वास्तव में यह जोनाथन फिंगलैंड के संपादित उत्तर के लगभग ठीक हो जाएगा जो पहले ही सही हो चुका है।
वज़

14

अंडरस्कोर में एक विस्तार विधि भी है:

गंतव्य ऑब्जेक्ट पर स्रोत ऑब्जेक्ट में सभी गुणों की प्रतिलिपि बनाएँ। यह क्रम में है, इसलिए अंतिम स्रोत पिछले तर्कों में एक ही नाम के गुणों को ओवरराइड करेगा।

_.extend(destination, *sources) 

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}


6

क्या आप एक संपत्ति को अधिलेखित करना चाहते हैं यदि नाम समान हैं लेकिन मान नहीं हैं?

और क्या आप मूल वस्तुओं में से किसी एक को स्थायी रूप से बदलना चाहते हैं,

या क्या आप एक नई मर्ज की गई वस्तु वापस चाहते हैं?

function mergedObject(obj1, obj2, force){
    for(var p in obj1) this[p]= obj1[p];
    for(var p in obj2){
        if(obj2.hasOwnProperty(p)){
            if(force || this[p]=== undefined) this[p]= obj2[p];
            else{
                n= 2;
                while(this[p+n]!== undefined)++n;
                this[p+n]= obj2[p];
            }
        }
    }
}

6

अपना खुद का विस्तार / मिक्सिन फंक्शन रोलिंग

function extend(objects) {
    var args
        , first = Array.prototype.slice.call(arguments, 0, 1)[0]
        , second;

    if (arguments.length > 1) {
        second = Array.prototype.splice.call(arguments, 1, 1)[0];
        for (var key in second) {
            first[key] = second[key];
        }
        args = Array.prototype.slice.call(arguments, 0);
        return extend.apply(this, args);
    }

    return first;
}

...

var briansDirections = {
    step1: 'Remove pastry from wrapper.',
    step2: 'Place pastry toaster.',
    step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });

...

यह बस वस्तुओं की एक परत का विस्तार करता है , पुनरावर्ती रूप से। यह भी ध्यान दें कि यह पुनरावर्ती कार्य TCO ( टेल-कॉल ऑप्टिमाइज़्ड ) है क्योंकि इसकी वापसी अपने आप में अंतिम कॉल है।

इसके अतिरिक्त, आप लक्षित गुण चाहते हैं । इस मामले में, आप वस्तुओं को आधार बनाना चाहते हैं id,quantity या उसे किसी अन्य संपत्ति। इस दृष्टिकोण में इसके बारे में एक छोटी सी पुस्तक लिखी जा सकती है और इसके लिए ऑब्जेक्ट-जूसकप की आवश्यकता होती है और यह बहुत जटिल हो सकता है। मैंने इसके लिए एक छोटी सी लाइब्रेरी लिखी है जो अनुरोध पर उपलब्ध है।

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


4
  1. जावास्क्रिप्ट में सहयोगी सरणी की कोई धारणा नहीं है, ऑब्जेक्ट हैं
  2. दो वस्तुओं को मर्ज करने का एकमात्र तरीका उनकी संपत्तियों के लिए लूप करना है और उनके मूल्यों की ओर संकेत करना है जो कि आदिम प्रकार और किसी अन्य उदाहरण के लिए आदिम प्रकार के लिए मान नहीं हैं।

8
जावास्क्रिप्ट में वस्तुओं को साहचर्य सरणियों के रूप में लागू किया जाता है, इसलिए निश्चित रूप से उसी की धारणा है
ऑक्सीजन

2

2019 में आपके पास 2 अच्छे विकल्प हैं:

ऑब्जेक्ट असाइन करना [ डॉक्टर ]

const result = Object.assign({}, baseObject, updatingObject);

फैली हुई वस्तु [ डॉक्टर ]

const result = { ...baseObject, ...updatingObject};

पहले वाला अधिक सुरक्षित, अधिक मानक और पॉलीवलेंट हो जाता है। एक अच्छा पेशेवरों और विपक्ष यहाँ



1

गहरी नकल के लिए जूलरी में बूलियन होता है। आप ऐसा कुछ कर सकते हैं:

MergeRecursive = function(arr1, arr2){
    $.extend(true, arr1, arr2);
    return arr1;                
};

साथ ही आप इस फ़ंक्शन को मर्ज करने के लिए n-सरणियों का समर्थन करने के लिए संपादित कर सकते हैं।

ArrayMergeRecursive = function(){
     if(arguments.length < 2){
          throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
     }

    var arr1=arguments[0];
    for(var i=0; i<=arguments.length; i++ ){
        $.extend(true, arr1, arguments[i]);                 
    }

    return arr1;                
};

तो अब आप कर सकते हैं

var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
    arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
    arr3 = ['Peter','Jhon','Demosthenes'],
    results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);

0

मुझे एक गहरी वस्तु-विलय की आवश्यकता थी। इसलिए अन्य सभी उत्तरों से मुझे बहुत मदद नहीं मिली। _.extend और jQuery.extend अच्छा करते हैं, जब तक कि आपके पास पुनरावर्ती सरणी नहीं है जैसे कि मैं करता हूं। लेकिन यह इतना बुरा नहीं है, आप इसे पाँच मिनट में प्रोग्राम कर सकते हैं:

var deep_merge = function (arr1, arr2) {
    jQuery.each(arr2, function (index, element) {
        if (typeof arr1[index] === "object" && typeof element === "object") {
            arr1[index] = deep_merge(arr1[index], element);
        } else if (typeof arr1[index] === "array" && typeof element === "array") {
            arr1[index] = arr1[index].concat(element);
        } else {
            arr1[index] = element;
        }
    });
    return arr1;
}

0

JQuery में सरणियों को मर्ज करने के लिए $ .merge के बारे में क्या?

var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';

0

पुनरावर्ती समाधान (वस्तुओं के सरणियों का विस्तार भी) + अशक्त जाँच

var addProps = function (original, props) {
    if(!props) {
        return original;
    }
    if (Array.isArray(original)) {
        original.map(function (e) {
            return addProps(e, props)
        });
        return original;
    }
    if (!original) {
        original = {};
    }
    for (var property in props) {
        if (props.hasOwnProperty(property)) {
            original[property] = props[property];
        }
    }
    return original;
};

टेस्ट

console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));

[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }

मैंने नोड जेएस के साथ इसका उपयोग करने की कोशिश की, लेकिन Object.getOwnPropertyNames is not a functionऐप को क्रैश कर देगा।
लेगलेस

मैं कुछ पुराने v8 इंजन के साथ plv8 PostgreSQL एक्सटेंशन में इसका उपयोग कर रहा हूं। और यह ब्राउज़रों में काम करता है। बस अपने JS इंजन में एक तरीका ढूंढें "समद्विभाजक" के रूप में समकक्ष कार्य करें। तब आप इस तर्क का पुन: उपयोग कर सकते हैं।
sscarduzio

0

यहाँ सबसे अच्छा समाधान है।

obj1.unshift.apply( obj1, obj2 );

इसके अलावा, obj1किसी भी समस्या के बिना एक लूप के अंदर बढ़ सकता है। (कहते हैं obj2कि गतिशील है)

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