जावास्क्रिप्ट - क्या निर्दिष्ट कुंजी संपत्ति द्वारा 2 वस्तुओं को मर्ज करने का कोई तरीका है? इस मामले में मुख्य गुण authorId है।

नोट: लेखक 3 और लेखक 1 का मेल नहीं है, इसलिए उनका विलय नहीं होना चाहिए।

var b = [{"book": "book1", "authorId": 3},{"book": "book2", "authorId":2}];

var a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];

var c = a.merge(b);

console.log(c);

उम्मीद करना:

[{"book": "book2", "authorId": 2, "author": "author2"}]

मैं यहां पूरा करने की कोशिश कर रहा हूं कि एसक्यूएल जॉइन क्या करता है।

https://jsfiddle.net/x67fpwoj/4/

0
Rod 4 अगस्त 2018, 01:01

3 जवाब

map द्वारा Object.assign समान अनुक्रमणिका के साथ अन्य सरणी में आइटम से:

var b = [{"book": "book1", "authorId": 1},{"book": "book2", "authorId":2}];
var a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];
var c = a.map((aItem, i) => Object.assign({}, aItem, b[i]));
console.log(c);

यदि आप ऑर्डर की जा रही प्रत्येक सरणी पर भरोसा नहीं कर सकते हैं, तो आप reduce को authorId द्वारा अनुक्रमित ऑब्जेक्ट में कर सकते हैं, और फिर उस ऑब्जेक्ट के मान प्राप्त कर सकते हैं (इसमें O(N) के बजाय जटिलता है O(N) .find प्रत्येक पुनरावृत्ति पर, जिसमें O(N^2) जटिलता होगी):

var a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];
var b = [{"book": "book1", "authorId": 1},{"book": "book2", "authorId":2}];

const reduceByAuthor = (arr, initial = {}) => arr.reduce((a, item) => {
  a[item.authorId] = Object.assign((a[item.authorId] || {}), item);
  return a;
}, initial);

const indexedByAuthor = reduceByAuthor(a);
reduceByAuthor(b, indexedByAuthor);
console.log(Object.values(indexedByAuthor));

यदि आप भी पर भरोसा नहीं कर सकते हैं कि प्रत्येक आइटम का अन्य एरे में एक मैच है, तो reduce दो बार, दूसरे reduce के साथ एक्यूमुलेटर को केवल तभी असाइन करें जब एक मैच था पहले अनुक्रमित वस्तु में पाया गया (बाद में filtering से तेज):

var b = [{"book": "book1", "authorId": 3},{"book": "book2", "authorId":2}];
var a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];

const aIndexed = a.reduce((a, item) => {
  a[item.authorId] = item;
  return a;
}, {});
const c = Object.values(b.reduce((a, bItem) => {
  const { authorId } = bItem;
  const aItem = aIndexed[authorId];
  if (aItem) a[authorId] = Object.assign({}, aItem, bItem);
  return a;
}, {}))

console.log(c);
2
CertainPerformance 4 अगस्त 2018, 01:20
मैं नहीं देखता कि authorId कहां निर्दिष्ट है। यह कैसे पता चलेगा कि कैसे जुड़ना है?
 – 
Rod
4 अगस्त 2018, 01:04
क्योंकि iवाँ आइटम a सरणी में iवें आइटम से मेल खाता है b पहले से ही (आपके उदाहरण के अनुसार), इसकी जांच करने की कोई आवश्यकता नहीं है - आप बस प्रत्येक सरणी से iवें आइटम को एक साथ मर्ज कर सकते हैं।
 – 
CertainPerformance
4 अगस्त 2018, 01:06
1
return Object.assign({}, aItem, b.find(bItem => bItem.authorId = aItem.authorId)) का उपयोग बेहतर होना चाहिए...
 – 
Sphinx
4 अगस्त 2018, 01:07
1
मुझे पूरा यकीन है कि यह वह नहीं है जो पूछने वाला ढूंढ रहा है। यह मानता है कि ऑर्डरिंग बिल्कुल सही है और वास्तव में इन दो सरणियों को समझदारी से मर्ज नहीं करता है।
 – 
BShaps
4 अगस्त 2018, 01:07
यदि आपका इनपुट आवश्यक रूप से आदेशित नहीं है, तो कृपया अपने प्रश्न या इसके उदाहरण को स्पष्ट करने के लिए संपादित करें।
 – 
CertainPerformance
4 अगस्त 2018, 01:08

मान लें कि आपको शामिल होने के लिए फ़ील्ड निर्दिष्ट करने की आवश्यकता है (चूंकि आपने सिंटैक्स की तरह SQL का उल्लेख किया है) और प्रदर्शन के बारे में बहुत अधिक चिंता किए बिना (यदि ऐसा है तो आपको ऑब्जेक्ट को मर्ज करने के लिए एक इंडेक्स बनाने की आवश्यकता होगी, लेकिन नीचे दिए गए पूर्ण नोट को पढ़ें ) तो आप ऑब्जेक्ट सरणियों को मर्ज करने के लिए कुछ सरणी विधियों और एक विनाशकारी असाइनमेंट का उपयोग कर सकते हैं।

const b = [{"book": "book1", "authorId": 3},{"book": "book2", "authorId":2}];

const a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];

// Using reduce will allow filtering of unmatched records
const merge = (field, x, z) => x.reduce((out, v) => {
  // Make sure the field exists in the object to merge
  // Using find will return the first object that matches the criteria (multiple record matching was not mentioned as a concern in the OP)
  const match = v.hasOwnProperty(field) && z.find((c) => c[field] === v[field]);
  
  if (match) {
    // Only push onto the output array if there is a match
    // Use destructuring assignment to merge the matching objects
    out.push({...v, ...match});
  }

  return out;
}, []);

console.log(merge('authorId', a, b));

परफ नोट: कई कारणों से इंडेक्स दृष्टिकोण का उपयोग करने से सावधान रहें। उदाहरण के लिए जब मर्ज करने के लिए सेट किए गए डेटा की तुलना में मर्ज करने के लिए ऑब्जेक्ट बहुत छोटा होता है। अनुक्रमणिका बनाने में अधिक समय लग सकता है, फिर अपेक्षाकृत कम संख्या में मिलानों के लिए सरणी की खोज करना। आपको उनका उपयोग तब करना चाहिए जब यह समझ में आता है, लेकिन यह ध्यान में रखते हुए कि ऐसा करने के लिए यह एक सपाट कथन नहीं होना चाहिए।

पूर्णता के लिए, यहाँ एक ही कोड एक अस्थायी सूचकांक के साथ है:

const b = [{"book": "book1", "authorId": 3},{"book": "book2", "authorId":2}];

const a = [{"authorId": 1, "author": "author1"},{"authorId": 2, "author": "author2"}];

const merge = (field, x, z) => {
  const index = z.reduce((out, v) => {
    if (v.hasOwnProperty(field)) {
      out[v[field]] = v;
    }
    
    return out;
  }, {});
  
  return x.reduce((out, v) => {
    const match = index[v[field]];

    if (match) {
      out.push({...v, ...match});
    }

    return out;
  }, []);
};

console.log(merge('authorId', a, b));
1
Jason Cust 4 अगस्त 2018, 07:41

मुझे लगता है कि यह वही करेगा जो आपको स्पष्ट कोड के साथ चाहिए:

var c = [];
b.map(item1 => {
  a.map(item2 => {
    if (item1.authorId === item2.authorId) {
      c.push(Object.assign(item1, item2));
    }
  })
});
console.log(c);
0
Ezzat Elbadrawy 4 अगस्त 2018, 02:13
मुझे नहीं पता क्यों?!
 – 
Ezzat Elbadrawy
4 अगस्त 2018, 05:57
यह b के प्रत्येक पुनरावृत्ति के लिए a में प्रत्येक आइटम पर पुनरावृति के यहां प्रदर्शन चिंता के कारण हो सकता है। यह एक अनुशंसित समाधान नहीं होगा।
 – 
Jason Cust
4 अगस्त 2018, 07:31