जावास्क्रिप्ट में सरणी चौराहे के लिए सबसे सरल कोड


607

जावास्क्रिप्ट में सरणी चौराहों को लागू करने के लिए सबसे सरल, पुस्तकालय-मुक्त कोड क्या है? मैं लिखना चाहता हूँ

intersection([1,2,3], [2,3,4,5])

और पाओ

[2, 3]

16
क्या आप सरल या तेज चाहते हैं?
SLAKs

11
प्राथमिकता सरल है, लेकिन यह इतना मस्तिष्क-मृत नहीं हो सकता है कि यह एक प्रदर्शन हॉग होगा :)
पीटर

4
मैंने यहां सभी विधियों के लिए एक JsFiddle Banchmark परीक्षण पृष्ठ बनाया है, जिसमें _underscore चौराहे फ़ंक्शन शामिल है। (अधिक बेहतर है) ! छवि विवरण यहां दर्ज करें अब तक intersect_safe ने सर्वोत्तम परिणाम दिए हैं । आप और सबसे खराब अंडरस्कोर।
neoswf

ऑप्स / सेक breakको Simple js loopsबढ़ाने के लिए a को जोड़ना ~ 10M
रिचर्ड

19
यदि आप इसे याद करते हैं : सरलतम उत्तर को स्वीकार नहीं किया जाता है, लेकिन तल में एक है: stackoverflow.com/questions/1885557/…
redben

जवाबों:


1076

के संयोजन का प्रयोग Array.prototype.filterऔर Array.prototype.indexOf:

array1.filter(value => -1 !== array2.indexOf(value))

या जैसा कि टिप्पणियों में सुझाए गए vrugtehagel , आप और Array.prototype.includesभी सरल कोड के लिए हाल ही में उपयोग कर सकते हैं :

array1.filter(value => array2.includes(value))

पुराने ब्राउज़रों के लिए:

array1.filter(function(n) {
    return array2.indexOf(n) !== -1;
});

9
जिसे आप सरणी के प्रोटोटाइप पर लाइब्रेरी संस्करण जोड़कर हल कर सकते हैं।
आनन।

12
हां, लेकिन यह ध्यान देने योग्य था।
टिम डाउन

18
यहां सबसे अच्छा जवाब, सादगी के लिए और गैर-संख्या के साथ काम करने के लिए
मुहम्मद

41
intersection([1,2,1,1,3], [1])लौटता है [1, 1, 1]। क्या यह अभी वापस नहीं आना चाहिए [1]?
edjroot

21
के बजाय array2.indexOf(n) != -1एक array2.includes(n)भी सरल कोड के लिए लिख सकते हैं ।
vrugtehagel

157

विनाशकारी सबसे सरल लगता है, खासकर अगर हम मान सकते हैं कि इनपुट सॉर्ट किया गया है:

/* destructively finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *  State of input arrays is undefined when
 *  the function returns.  They should be 
 *  (prolly) be dumped.
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length, b.length)
 */
function intersection_destructive(a, b)
{
  var result = [];
  while( a.length > 0 && b.length > 0 )
  {  
     if      (a[0] < b[0] ){ a.shift(); }
     else if (a[0] > b[0] ){ b.shift(); }
     else /* they're equal */
     {
       result.push(a.shift());
       b.shift();
     }
  }

  return result;
}

गैर-विनाशकारी बालों को अधिक जटिल होना पड़ता है, क्योंकि हमें सूचकांक ट्रैक करने के लिए मिला है:

/* finds the intersection of 
 * two arrays in a simple fashion.  
 *
 * PARAMS
 *  a - first array, must already be sorted
 *  b - second array, must already be sorted
 *
 * NOTES
 *
 *  Should have O(n) operations, where n is 
 *    n = MIN(a.length(), b.length())
 */
function intersect_safe(a, b)
{
  var ai=0, bi=0;
  var result = [];

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
}

14
इसमें कई त्रुटियां हैं intersect_safe: lengthएरेस में एक संपत्ति है, एक विधि नहीं है। इसमें एक अनियंत्रित चर iहै result.push(a[i]);। अंत में, यह केवल सामान्य स्थिति में काम नहीं करता है: दो वस्तुएं जहां >ऑपरेटर के अनुसार न तो दूसरे की तुलना में अधिक हो, जरूरी नहीं कि समान हो। intersect_safe( [ {} ], [ {} ] ), उदाहरण के लिए, एक तत्व के साथ एक सरणी (एक बार पहले उल्लिखित त्रुटियों को ठीक कर दिया जाता है) देगा, जो स्पष्ट रूप से गलत है।
टिम डाउन

1
@ समय कम करें: आपके द्वारा इंगित सिंटैक्स त्रुटियों को ठीक किया। चाहे वह कुछ भी विचार करने के लिए सही या गलत हो, न तो गेरेटर और न ही कम होना समान होना आवश्यकताओं पर निर्भर करता है। मुझे यह कहते हुए मूल प्रश्न में कुछ भी ध्यान नहीं है कि सामग्री में सरणियाँ होने की उम्मीद है। अब, आपको यह कहना सही होगा कि अप्रत्याशित इनपुट को संभाला जाना चाहिए, लेकिन अगर यह कल्पना पहले से ही हो गई थी कि इनपुट को संख्याओं के सरणियों (जैसा कि मुझे लगता है) होना चाहिए, तो कोड ठीक होगा।
ATK

1
@atk: मैं आपकी बात पर ध्यान देता हूं, उदाहरण के रूप में प्रश्न में उदाहरण एरे का उपयोग करता है जिसमें केवल संख्याएँ होती हैं।
टिम डाउन

4
आप अनुक्रमणिका को ट्रैक करने के बजाय .slice(0)सरणी का एक क्लोन बनाने के लिए भी उपयोग कर सकते हैं intersect_safe
जॉन्हुलेटके सिप

1
@thesmart: आप सही कह रहे हैं, इसे करने के लिए निश्चित रूप से अधिक प्रदर्शन करने के तरीके हैं। कोड, ऊपर, सरल, तेजी से नहीं हो :) इरादा था
ATK

57

यदि आपका वातावरण ECMAScript 6 सेट का समर्थन करता है , तो एक सरल और माना जाता है कि कुशल (विनिर्देश लिंक देखें):

function intersect(a, b) {
  var setA = new Set(a);
  var setB = new Set(b);
  var intersection = new Set([...setA].filter(x => setB.has(x)));
  return Array.from(intersection);
}

कम, लेकिन कम पठनीय (अतिरिक्त चौराहे बनाए बिना Set):

function intersect(a, b) {
      return [...new Set(a)].filter(x => new Set(b).has(x));
}

हर बार नए Setसे बचना b:

function intersect(a, b) {
      var setB = new Set(b);
      return [...new Set(a)].filter(x => setB.has(x));
}

ध्यान दें कि सेट का उपयोग करते समय आपको केवल अलग-अलग मान प्राप्त होंगे, इस प्रकार इसका new Set[1,2,3,3].sizeमूल्यांकन होता है 3


1
यह [...setA]वाक्य रचना क्या है ? कुछ खास तरह के जावास्क्रिप्ट ऑपरेशन?
jxramos

1
@jxramos जो स्प्रेड सिंटैक्स है और इस मामले में इसका उपयोग सेट में तत्वों से एक सरणी बनाने के लिए किया जा रहा है। "Array.from (setA)" भी इस मामले में काम करेगा, लेकिन चूंकि प्रश्न "सरलतम" के लिए पूछा गया था, इसलिए मैंने उस लाइन पर पढ़ने के लिए इसे क्लीनर बनाने की कोशिश की। उस मामले पर, मुझे लगता है कि कोड सरल हो सकता है, इसलिए मैं स्निपेट को अपडेट करूंगा।
नर्बोसा

@nbbosa मैं उत्सुक हूं: आपने सरणी को "क्लोन" क्यों किया? #filter मूल सरणी को नष्ट नहीं करता है, है ना? यह एक नई सरणी बनाता है?
bplittle

@bplittle मैंने केवल डुप्लिकेट को निकालने के लिए सेट से एक सरणी बनाई है, अन्यथा, सीधे सरणी का उपयोग करने से डुप्लिकेट वापस आ जाएगा। उदाहरण के लिए, अगर मैंने सीधे ऐरे का उपयोग किया, तो प्रतिच्छेद ([१,२,२,४,४], [२,३]] उपज होगी [२, २]।
nbarbosa

2
हर बार निष्पादित होने पर वह x => new Set(b).has(x)तीर फ़ंक्शन bएक सेट में नहीं बदल जाता है ? आपको शायद उस सेट को एक चर में सहेजना चाहिए।
अरन-फे

39

Underscore.js या lodash.js का उपयोग करना

_.intersection( [0,345,324] , [1,0,324] )  // gives [0,324]

20
Op ने "पुस्तकालय-मुक्त" के लिए कहा।
LinuxDisciple

@LinuxDisciple लापता होने के लिए मेरी गलती है। नोट के लिए धन्यवाद
साईं राम

33
किसी भी मामले में, यह इस खोज के लिए शीर्ष Google लिस्टिंग है, इसलिए लाइब्रेरी का उत्तर उपयोगी है। धन्यवाद।
वेबनोब

मुझे भी खुशी है कि यह पोस्ट किया गया था। पहली बार मैंने अंडरस्कोर की जरूरत महसूस की है। जे.एस. आमतौर पर जावास्क्रिप्ट मैप और पाइपलाइनों को कम करना काम को सुरुचिपूर्ण ढंग से करते हैं लेकिन इस बार नहीं।
श्रीधर सरनोबत

मैं <3 अंडरस्कोर और मैं <3 जेरेमी एशकेनास (इसके निर्माता), लेकिन फिर भी मैं इसके बजाय लोदी को बाहर की जाँच करने की सलाह देता हूं। यह मूल रूप से अंडरस्कोर का एक बेहतर संस्करण है (यह मूल रूप से एक कांटा था) जिसका केवल नकारात्मक पक्ष सुपर-अनुकूलित (और इस प्रकार लगभग अपठनीय) स्रोत कोड है। अंडरस्कोर के लोगों ने अंडरस्कोर से पूरी तरह से छुटकारा पाने पर भी विचार किया (और सिर्फ लोगों को लॉडश का उपयोग करने के लिए कह रहा था), लेकिन जो लोग स्रोत कोड की पठनीयता की परवाह करते हैं, उन्होंने इसे रखने के लिए तर्क दिया (मैं वास्तव में उस तरफ था, लेकिन मैंने तब से लॉडश में बदल दिया है)। @see github.com/jashkenas/underscore/issues/2182
machineghost

14

ईएस 6 शब्दों में मेरा योगदान। सामान्य तौर पर यह एक सरणी के चौराहे को तर्कों के रूप में प्रदान की गई अनिश्चित संख्या में अनिश्चित काल का होता है।

Array.prototype.intersect = function(...a) {
  return [this,...a].reduce((p,c) => p.filter(e => c.includes(e)));
}
var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]],
     arr = [0,1,2,3,4,5,6,7,8,9];

document.write("<pre>" + JSON.stringify(arr.intersect(...arrs)) + "</pre>");


यह कोड बहुत अच्छा लग रहा है, लेकिन मैं इसे पूरी तरह से नहीं समझता। कृपया इसे समझाना संभव है?
theusual

1
@novembersky यह एक सरणी की तरह सभी विषय सरणियों को इकट्ठा करता है [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7],[4,6]]और फिर लागू होता है .reduce()। सबसे पहले [0,1,2,3,4,5,6,7,8,9].filter( e => [0,2,4,6,8].includes(e)आपरेशन किया जाता है और परिणाम नया हो जाता है pऔर cहो जाता है [4,5,6,7]अगली बारी में और ऊपर पर तो जारी है जब तक कोई और अधिक cछोड़ दिया है।
रेडू

1
यदि आप बड़े डेटा सेट के साथ काम कर रहे हैं तो यह एक महंगा समाधान है।
मेडब्रेक्स ऑक्ट

1
prototypeअनावश्यक रूप से संशोधित न करें ।
fregante

14

// Return elements of array a that are also in b in linear time:
function intersect(a, b) {
  return a.filter(Set.prototype.has, new Set(b));
}

// Example:
console.log(intersect([1,2,3], [2,3,4,5]));

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

विकल्प और प्रदर्शन तुलना:

वैकल्पिक कार्यान्वयन के लिए निम्नलिखित स्निपेट देखें और प्रदर्शन तुलना के लिए https://jsperf.com/array-intersection-comparison देखें

फ़ायरफ़ॉक्स 53 में परिणाम:

  • बड़े सरणियों पर ऑप्स / सेक (10,000 तत्व):

    filter + has (this)               523 (this answer)
    for + has                         482
    for-loop + in                     279
    filter + in                       242
    for-loops                          24
    filter + includes                  14
    filter + indexOf                   10
  • छोटे सरणियों पर ऑप्स / सेक (100 तत्व):

    for-loop + in                 384,426
    filter + in                   192,066
    for-loops                     159,137
    filter + includes             104,068
    filter + indexOf               71,598
    filter + has (this)            43,531 (this answer)
    filter + has (arrow function)  35,588

2
intersect([1,2,2,3], [2,3,4,5])लौटता है [2, 2, 3]
सेरेगीपी

1
@SeregPie बिल्कुल सही। टिप्पणी के अनुसार "सरणी के तत्व जो a भी b में हैं"
le_m

गुणवत्ता का जवाब, हालाँकि ऑप्स के उपयोग से परिणाम मूल रूप से बदल जाता है क्योंकि ऑप्स सवाल केवल सरणी चौराहों के बारे में पूछते हैं और डुप्लिकेट को कैसे संभालना है, इसका कोई उल्लेख / उल्लेख नहीं करता है। इस कारण से, यह उत्तर डुप्लिकेट मौजूद होने पर अप्रत्याशित परिणाम दे सकता है।
मेडब्रेक्स ऑक्ट

1
इसे प्यार करें, लेकिन आपने "फ़िल्टर + शामिल" के साथ एक अनावश्यक फ़ंक्शन जोड़ा है। कोशिश करो a.filter(b.includes)। यह काफी तेज चलना चाहिए (आपके फ़ंक्शन अपग्रेड के समान)।
15

11

कैसे सिर्फ साहचर्य सरणियों का उपयोग करने के बारे में?

function intersect(a, b) {
    var d1 = {};
    var d2 = {};
    var results = [];
    for (var i = 0; i < a.length; i++) {
        d1[a[i]] = true;
    }
    for (var j = 0; j < b.length; j++) {
        d2[b[j]] = true;
    }
    for (var k in d1) {
        if (d2[k]) 
            results.push(k);
    }
    return results;
}

संपादित करें:

// new version
function intersect(a, b) {
    var d = {};
    var results = [];
    for (var i = 0; i < b.length; i++) {
        d[b[i]] = true;
    }
    for (var j = 0; j < a.length; j++) {
        if (d[a[j]]) 
            results.push(a[j]);
    }
    return results;
}

1
यह केवल एक मौका होता है यदि आपके सरणियों में केवल तार या संख्याएं होती हैं, और यदि आपके पृष्ठ की कोई भी स्क्रिप्ट में गड़बड़ नहीं हुई है Object.prototype
टिम डाउन

2
ओपी का उदाहरण संख्याओं का उपयोग कर रहा था, और यदि किसी स्क्रिप्ट ने Object.prototyp के साथ गड़बड़ की है, तो स्क्रिप्ट को फिर से लिखा या हटाया जाना चाहिए।
स्टीवन हुआविग

आपको (d1) और (d2) दोनों की आवश्यकता नहीं है। बनाएँ (डी 2), फिर (डी 1) के माध्यम से लूपिंग के बजाय (ए) के माध्यम से लूप करें।
स्टेनली

d[b[i]] = true;इसके बजाय d[b[j]] = true;( iनहीं j) होना चाहिए । लेकिन संपादित करने के लिए 6 वर्णों की आवश्यकता होती है।
इज़्हाकी

@ इजाकी धन्यवाद, तय। (न्यूनतम संपादित आवश्यकता को प्राप्त करने के लिए एक // टिप्पणी जोड़ा गया।)
स्टीवन Huwig

8
  1. हल करे
  2. इंडेक्स 0 से एक-एक करके चेक करें, उससे नया ऐरे बनाएं।

कुछ इस तरह, हालांकि अच्छी तरह से परीक्षण नहीं किया गया।

function intersection(x,y){
 x.sort();y.sort();
 var i=j=0;ret=[];
 while(i<x.length && j<y.length){
  if(x[i]<y[j])i++;
  else if(y[j]<x[i])j++;
  else {
   ret.push(x[i]);
   i++,j++;
  }
 }
 return ret;
}

alert(intersection([1,2,3], [2,3,4,5]));

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


3
छंटनी आवश्यक रूप से मनमानी वस्तुओं के सरणियों के लिए मदद नहीं करेगी
टिम डाउन

यदि सरणी को क्रमबद्ध नहीं किया गया है, तो आपको 1000 लंबाई सरणी x 1000 लंबाई सरणी
आप

मुझे लगता है कि आपने मेरी बात को याद किया, जो यह है कि जावास्क्रिप्ट में मनमानी वस्तुओं का कोई प्राकृतिक क्रम नहीं है, जिसका अर्थ है कि मनमानी वस्तुओं की एक सरणी को छाँटने से समान वस्तुओं को समूहीकृत नहीं किया जाएगा। यह एक कुशल एल्गोरिथ्म है जो काम नहीं करता है अच्छा नहीं है।
टिम डाउन

क्षमा करें, मुझे "मनमानी वस्तुएं" याद आईं, हां, आप सही हैं। वे ऑब्जेक्ट इसे सॉर्ट नहीं कर सकते हैं, और एल्गोरिथ्म उन पर काम नहीं कर सकता है।
आप

8

आदिमों की सॉर्ट किए गए सरणियों के लिए @ एटीके के कार्यान्वयन का प्रदर्शन .shift के बजाय .op का उपयोग करके सुधार किया जा सकता है।

function intersect(array1, array2) {
   var result = [];
   // Don't destroy the original arrays
   var a = array1.slice(0);
   var b = array2.slice(0);
   var aLast = a.length - 1;
   var bLast = b.length - 1;
   while (aLast >= 0 && bLast >= 0) {
      if (a[aLast] > b[bLast] ) {
         a.pop();
         aLast--;
      } else if (a[aLast] < b[bLast] ){
         b.pop();
         bLast--;
      } else /* they're equal */ {
         result.push(a.pop());
         b.pop();
         aLast--;
         bLast--;
      }
   }
   return result;
}

मैंने jsPerf: http://bit.ly/P9FrZK का उपयोग करके एक बेंचमार्क बनाया । यह उपयोग करने के लिए लगभग तीन गुना तेज है।


1
बस दूसरों के लिए एक साइड नोट के रूप में - यह केवल संख्याओं के लिए काम करेगा, तार नहीं।
इज़्हाकी

ध्यान दें कि अगर आप को बदलने के a[aLast] > b[bLast]साथ a[aLast].localeCompare(b[bLast]) > 0(और साथ ही else ifनीचे) तो यह तार पर काम करेंगे।
एंड्रयू

1
गति अंतर सरणियों के आकार पर निर्भर करता है क्योंकि .popO (1) है और .shift()O (n) है
Esailija

8

JQuery का उपयोग करना :

var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);

8
यह भी लिखा जा सकता है c = $(b).filter(a);, लेकिन मैं इस तरह के सरणी हेरफेर के लिए jQuery पर भरोसा करने की सिफारिश नहीं करूंगा क्योंकि प्रलेखन में केवल यह उल्लेख है कि यह तत्वों के लिए काम करता है।
स्ट्राइकर

1
यह
ऑप्स

7

केवल स्ट्रिंग या संख्या वाले सरणियों के लिए आप कुछ अन्य उत्तरों के अनुसार छंटाई के साथ कुछ कर सकते हैं। मनमानी वस्तुओं के सरणियों के सामान्य मामले के लिए मुझे नहीं लगता कि आप इसे लंबा करने से बच सकते हैं। निम्नलिखित आपको मापदंडों के रूप में प्रदान की गई किसी भी संख्या में सरणियों का प्रतिच्छेदन देगा arrayIntersection:

var arrayContains = Array.prototype.indexOf ?
    function(arr, val) {
        return arr.indexOf(val) > -1;
    } :
    function(arr, val) {
        var i = arr.length;
        while (i--) {
            if (arr[i] === val) {
                return true;
            }
        }
        return false;
    };

function arrayIntersection() {
    var val, arrayCount, firstArray, i, j, intersection = [], missing;
    var arrays = Array.prototype.slice.call(arguments); // Convert arguments into a real array

    // Search for common values
    firstArray = arrays.pop();
    if (firstArray) {
        j = firstArray.length;
        arrayCount = arrays.length;
        while (j--) {
            val = firstArray[j];
            missing = false;

            // Check val is present in each remaining array 
            i = arrayCount;
            while (!missing && i--) {
                if ( !arrayContains(arrays[i], val) ) {
                    missing = true;
                }
            }
            if (!missing) {
                intersection.push(val);
            }
        }
    }
    return intersection;
}

arrayIntersection( [1, 2, 3, "a"], [1, "a", 2], ["a", 1] ); // Gives [1, "a"]; 

यह केवल उस मामले में काम करता है जहां वस्तु पहचान समानता का एकमात्र रूप है।
स्टीवन हुआविग

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

मुझे लगता है कि आप गलती से अपने उदाहरण में एक वैश्विक चर FirstArr बना रहे हैं।
जेसन जैक्सन

@ जैसनजैकसन: आप सही कह रहे हैं, धन्यवाद। चर को कॉल करने के लिए firstArrया firstArrayसंदर्भ के सभी अद्यतन नहीं किया था या नहीं, इस बारे में स्पष्ट रूप से मेरा विचार बदल गया । फिक्स्ड।
टिम डाउन

7

ES2015 और सेट का उपयोग करना बहुत छोटा है। स्ट्रिंग की तरह एरे-जैसे मानों को स्वीकार करता है और डुप्लिकेट को निकालता है।

let intersection = function(a, b) {
  a = new Set(a), b = new Set(b);
  return [...a].filter(v => b.has(v));
};

console.log(intersection([1,2,1,2,3], [2,3,5,4,5,3]));

console.log(intersection('ccaabbab', 'addb').join(''));


सेट से सरणी में परिवर्तित करें [...] डुप्लिकेट आइटम, अच्छा विचार, धन्यवाद को हटा देगा
V-SHY

1
यह समाधान आपके लिए दो बार पहले प्रदान किया गया था।
Madbreaks

7

तुम एक इस्तेमाल कर सकते हैं Setके रूप में thisArgकी Array#filterऔर ले Set#hasकॉलबैक के रूप में।

function intersection(a, b) {
    return a.filter(Set.prototype.has, new Set(b));
}

console.log(intersection([1, 2, 3], [2, 3, 4, 5]));


मुझे नहीं पता कि इसे अधिक वोट क्यों नहीं मिले। यह स्पष्ट रूप से सबसे अच्छा जवाब है।
पॉल रूनी

5

एक छोटी सी छोटी को यहाँ ( फ़िल्टर / इंडेक्सऑफ़ सॉल्यूशन ) के लिए एक छोटा ट्वीक , अर्थात् जावास्क्रिप्ट ऑब्जेक्ट का उपयोग करके किसी एक सरणियों में मानों का एक इंडेक्स बनाते हुए, इसे O (N * M) से "संभवतः" रैखिक समय तक कम कर देगा। source1 सोर्स 2

function intersect(a, b) {
  var aa = {};
  a.forEach(function(v) { aa[v]=1; });
  return b.filter(function(v) { return v in aa; });
}

यह सबसे सरल समाधान नहीं है (यह फ़िल्टर + इंडेक्सऑफ़ की तुलना में अधिक कोड है ), और न ही यह बहुत तेज़ है (संभवत: intersect_safe () की तुलना में एक स्थिर कारक द्वारा धीमा है ), लेकिन एक बहुत अच्छा संतुलन की तरह लगता है। यह बहुत सरल पक्ष पर है, जबकि अच्छा प्रदर्शन प्रदान करता है, और इसके लिए पूर्व-सॉर्ट किए गए इनपुट की आवश्यकता नहीं होती है।


5

एक और अनुक्रमित दृष्टिकोण किसी भी संख्या में सरणियों को एक साथ संसाधित करने में सक्षम है:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = 0;
            index[v]++;
        };
    };
    var retv = [];
    for (var i in index) {
        if (index[i] == arrLength) retv.push(i);
    };
    return retv;
};

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

intersect ([arr1, arr2, arr3...]);

... लेकिन यह पारदर्शी रूप से वस्तुओं को पैरामीटर के रूप में स्वीकार करता है या किसी भी तत्व को प्रतिच्छेद करने के लिए (हमेशा सामान्य मानों की सरणी लौटाता है)। उदाहरण:

intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]

संपादित करें: मैंने अभी देखा कि यह एक तरह से थोड़ा छोटी गाड़ी है।

अर्थात: मैंने यह सोचकर कोडित किया है कि इनपुट सरणियों में स्वयं पुनरावृत्ति नहीं हो सकती (जैसा कि उदाहरण दिया गया है)।

लेकिन यदि इनपुट सरणियों में पुनरावृत्ति होती है, तो यह गलत परिणाम देगा। उदाहरण (नीचे कार्यान्वयन का उपयोग करके):

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]

सौभाग्य से बस दूसरे स्तर के अनुक्रमण को जोड़कर इसे ठीक करना आसान है। अर्थात्:

परिवर्तन:

        if (index[v] === undefined) index[v] = 0;
        index[v]++;

द्वारा:

        if (index[v] === undefined) index[v] = {};
        index[v][i] = true; // Mark as present in i input.

...तथा:

         if (index[i] == arrLength) retv.push(i);

द्वारा:

         if (Object.keys(index[i]).length == arrLength) retv.push(i);

पूरा उदाहरण:

// Calculate intersection of multiple array or object values.
function intersect (arrList) {
    var arrLength = Object.keys(arrList).length;
        // (Also accepts regular objects as input)
    var index = {};
    for (var i in arrList) {
        for (var j in arrList[i]) {
            var v = arrList[i][j];
            if (index[v] === undefined) index[v] = {};
            index[v][i] = true; // Mark as present in i input.
        };
    };
    var retv = [];
    for (var i in index) {
        if (Object.keys(index[i]).length == arrLength) retv.push(i);
    };
    return retv;
};

intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]); // [ '1' ]

2
यह एक छोटे से संशोधन के साथ सबसे अच्छा जवाब है। var v = लाइन जोड़ने के बाद if (typeof v == 'function') continue;और यह परिणामों में फ़ंक्शन जोड़ना छोड़ देगा। धन्यवाद!
ज़सोल्टी

साभार @Zsolti मैं आपके सुझाव को नहीं जोड़ता क्योंकि कार्य होने (और जिस तरह से हम इसे संभालना चाहते हैं) मूल प्रश्न के दायरे से बाहर है। लेकिन मेरा संपादन देखें: यदि आपके इनपुट सरणियों में पुनरावृत्ति हो सकती है, तो मूल कार्यान्वयन छोटी गाड़ी है। मैंने इसे अपने संपादन में तय किया। ... दूसरी ओर, यदि आप यह सुनिश्चित करने के लिए जानते हैं कि कोई पुनरावृत्ति नहीं होगी, तो मूल कार्यान्वयन थोड़ा सस्ता है।
बिटिफेट

... फ़ंक्शंस के बारे में, उन्हें भी इंटरसेक्ट किया जा सकता है: अगर हम उनका पता लगाते हैं जैसे @Zsolti कहते हैं (के साथ if (typeof v == 'function'), तो हम v.toString()इंडेक्स की कुंजी के रूप में इसके स्ट्रिफ़िकेशन ( ) का उपयोग कर सकते हैं । लेकिन, हमें इसे बरकरार रखने के लिए कुछ करने की ज़रूरत है।) ऐसा करने का सबसे आसान तरीका बस मूल फ़ंक्शन को एक साधारण बूलियन सही मान के बजाय मान के रूप में असाइन करना है। लेकिन, उस स्थिति में, इस स्थिति का पता लगाने और सही मान (फ़ंक्शन) को पुनर्स्थापित करने के लिए नवीनतम डिंडेक्सटन को भी बदल दिया जाना चाहिए।
बिटकॉइन

100 तत्वों के साथ 30 सरणियों के साथ यह कितनी तेजी से हो सकता है .. सीपीयू का उपयोग कैसे होता है?
सहायक

5

आप (IE को छोड़कर सभी ब्राउज़रों के लिए) का उपयोग कर सकते हैं:

const intersection = array1.filter(element => array2.includes(element));

या IE के लिए:

const intersection = array1.filter(element => array2.indexOf(element) !== -1);

अच्छा होगा अगर आप इसे एक फंक्शन में बदल सकते हैं
avalanche1

@ avalanche1 const चौराहा = (a1, a2) => a1.filter (e => a2.includes (e));
जोत 3

4
function intersection(A,B){
var result = new Array();
for (i=0; i<A.length; i++) {
    for (j=0; j<B.length; j++) {
        if (A[i] == B[j] && $.inArray(A[i],result) == -1) {
            result.push(A[i]);
        }
    }
}
return result;
}

4

आपके डेटा पर कुछ प्रतिबंधों के साथ, आप इसे रैखिक में कर सकते हैं समय !

के लिए धनात्मक पूर्णांक : एक "देखा / नहीं देखा" बूलियन के लिए एक सरणी मान मैप का उपयोग करें।

function intersectIntegers(array1,array2) { 
   var seen=[],
       result=[];
   for (var i = 0; i < array1.length; i++) {
     seen[array1[i]] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if ( seen[array2[i]])
        result.push(array2[i]);
   }
   return result;
}

वस्तुओं के लिए एक समान तकनीक है : एक डमी कुंजी लें, इसे array1 में प्रत्येक तत्व के लिए "सही" पर सेट करें, फिर array2 के तत्वों में इस कुंजी को देखें। काम पूरा होने पर साफ करें।

function intersectObjects(array1,array2) { 
   var result=[];
   var key="tmpKey_intersect"
   for (var i = 0; i < array1.length; i++) {
     array1[i][key] = true;
   }
   for (var i = 0; i < array2.length; i++) {
     if (array2[i][key])
        result.push(array2[i]);
   }
   for (var i = 0; i < array1.length; i++) {
     delete array1[i][key];
   }
   return result;
}

बेशक आपको यह सुनिश्चित करने की आवश्यकता है कि कुंजी पहले प्रकट नहीं हुई थी, अन्यथा आप अपना डेटा नष्ट कर देंगे ...


वैसे, यह आसानी से किसी भी संख्या में सरणियों को इंटरसेक्ट करने के लिए बढ़ाया जा सकता है: पूर्णांक द्वारा बूलियन को बदलें, और हर बार वृद्धि होने पर देखा जाता है: आप अंतिम दौर में चौराहे को आसानी से पढ़ सकते हैं।
टेरुलेन

दिलचस्प समाधान, मुझे यह पसंद है। अधिकांश अन्य समाधान O (n ^ 2) हैं, लेकिन यह O (n) है। मैंने पूर्णांक कोड को ericP के प्रदर्शन फ़िडल में जोड़ दिया यहाँ jsfiddle.net/321juyLu/2 । यह 3 आया, मुझे पसंद आया :)
rmcsharry

3

जो मेरे लिए सबसे अच्छा काम कर रहा है, मैं उसमें योगदान दूंगा:

if (!Array.prototype.intersect){
Array.prototype.intersect = function (arr1) {

    var r = [], o = {}, l = this.length, i, v;
    for (i = 0; i < l; i++) {
        o[this[i]] = true;
    }
    l = arr1.length;
    for (i = 0; i < l; i++) {
        v = arr1[i];
        if (v in o) {
            r.push(v);
        }
    }
    return r;
};
}


2

'use strict'

// Example 1
function intersection(a1, a2) {
    return a1.filter(x => a2.indexOf(x) > -1)
}

// Example 2 (prototype function)
Array.prototype.intersection = function(arr) {
    return this.filter(x => arr.indexOf(x) > -1)
} 

const a1 = [1, 2, 3]
const a2 = [2, 3, 4, 5]

console.log(intersection(a1, a2))
console.log(a1.intersection(a2))


2

ES2015 के साथ एक कार्यात्मक दृष्टिकोण

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

इन प्रतिबंधों में शामिल कार्यों की रचनाशीलता और पुन: प्रयोज्यता को बढ़ाया जाता है।

// small, reusable auxiliary functions

const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const apply = f => x => f(x);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// run it

console.log( intersect(xs) (ys) );

कृपया ध्यान दें कि मूल Setप्रकार का उपयोग किया जाता है, जिसमें एक लाभप्रद लुकअप प्रदर्शन होता है।

डुप्लिकेट से बचें

स्पष्ट रूप से पहले से बार-बार होने वाली वस्तुओं Arrayको संरक्षित किया जाता है, जबकि दूसरे Arrayको डी-डुप्लिकेट किया जाता है। यह वांछित व्यवहार हो सकता है या नहीं भी हो सकता है। यदि आपको एक अद्वितीय परिणाम की आवश्यकता है, तो बस dedupeपहले तर्क पर लागू हों :

// auxiliary functions

const apply = f => x => f(x);
const comp = f => g => x => f(g(x));
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// de-duplication

const dedupe = comp(afrom) (createSet);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];


// unique result

console.log( intersect(dedupe(xs)) (ys) );

के किसी भी संख्या के चौराहे की गणना Arrayरों

आप में से एक मनमाने ढंग से संख्या के चौराहे की गणना करना चाहते हैं Arrayरों सिर्फ रचना intersectके साथ foldl। यहाँ एक सुविधा समारोह है:

// auxiliary functions

const apply = f => x => f(x);
const uncurry = f => (x, y) => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);


// intersection

const intersect = xs => ys => {
  const zs = createSet(ys);
  return filter(x => zs.has(x)
     ? true
     : false
  ) (xs);
};


// intersection of an arbitrarily number of Arrays

const intersectn = (head, ...tail) => foldl(intersect) (head) (tail);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
const zs = [0,1,2,3,4,5,6];


// run

console.log( intersectn(xs, ys, zs) );


प्रभावशाली रूप से कार्यात्मक: यह पुष्टि करने के लिए एक डबल-टेक करना था कि हास्केल नहीं है। एकमात्र नाइटपिक है: (expr ? true : false)निरर्थक। उपयोग सिर्फ exprअगर वास्तविक बूलियन्स आवश्यक नहीं हैं, बस truthy / falsy।
जॉसे_कास्त्रो_नारूढ़

2

सरलता के लिए:

// Usage
const intersection = allLists
  .reduce(intersect, allValues)
  .reduce(removeDuplicates, []);


// Implementation
const intersect = (intersection, list) =>
  intersection.filter(item =>
    list.some(x => x === item));

const removeDuplicates = (uniques, item) =>
  uniques.includes(item) ? uniques : uniques.concat(item);


// Example Data
const somePeople = [bob, doug, jill];
const otherPeople = [sarah, bob, jill];
const morePeople = [jack, jill];

const allPeople = [...somePeople, ...otherPeople, ...morePeople];
const allGroups = [somePeople, otherPeople, morePeople];

// Example Usage
const intersection = allGroups
  .reduce(intersect, allPeople)
  .reduce(removeDuplicates, []);

intersection; // [jill]

लाभ:

  • गंदगी सरल
  • डेटा केंद्रित
  • सूचियों की मनमानी संख्या के लिए काम करता है
  • सूचियों की मनमानी लंबाई के लिए काम करता है
  • मूल्यों के मनमाने प्रकार के लिए काम करता है
  • मनमाने ढंग से क्रम के लिए काम करता है
  • आकार बनाए रखता है (किसी भी सरणी में पहली उपस्थिति का क्रम)
  • जहां संभव हो जल्दी बाहर निकलता है
  • स्मृति सुरक्षित, समारोह / सरणी प्रोटोटाइप के साथ छेड़छाड़ की कमी

कमियां:

  • उच्च स्मृति उपयोग
  • उच्च CPU उपयोग
  • कम करने की समझ की आवश्यकता है
  • डेटा प्रवाह की समझ की आवश्यकता है

आप इसे 3D इंजन या कर्नेल कार्य के लिए उपयोग नहीं करना चाहेंगे, लेकिन यदि आपको ईवेंट-आधारित ऐप में इसे चलाने में समस्या आ रही है, तो आपके डिज़ाइन में बड़ी समस्याएं हैं।


2

.reduceएक नक्शा बनाने के लिए, और .filterचौराहे को खोजने के लिए। deleteभीतर .filterकी अनुमति देता है हमें दूसरी सरणी के इलाज के लिए जैसे कि यह एक अद्वितीय सेट है।

function intersection (a, b) {
  var seen = a.reduce(function (h, k) {
    h[k] = true;
    return h;
  }, {});

  return b.filter(function (k) {
    var exists = seen[k];
    delete seen[k];
    return exists;
  });
}

मैं इस दृष्टिकोण के बारे में तर्क करने के लिए बहुत आसान लगता है। यह निरंतर समय में प्रदर्शन करता है।


2

यह शायद सबसे सरल है, इसके अलावा list1.filter (n => list2.includes (n))

var list1 = ['bread', 'ice cream', 'cereals', 'strawberry', 'chocolate']
var list2 = ['bread', 'cherry', 'ice cream', 'oats']

function check_common(list1, list2){
	
	list3 = []
	for (let i=0; i<list1.length; i++){
		
		for (let j=0; j<list2.length; j++){	
			if (list1[i] === list2[j]){
				list3.push(list1[i]);				
			}		
		}
		
	}
	return list3
	
}

check_common(list1, list2) // ["bread", "ice cream"]


यह O (nm) समय जटिलता है ... इसे O (n + m) में हल किया जा सकता है
alchuang

2

यदि आपको कई सरणियों को समाहित करने की आवश्यकता है, तो:

const intersect = (a, b, ...rest) => {
  if (rest.length === 0) return [...new Set(a)].filter(x => new Set(b).has(x));
  return intersect(a, intersect(b, ...rest));
};

console.log(intersect([1,2,3,4,5], [1,2], [1, 2, 3,4,5], [2, 10, 1])) // [1,2]


लेकिन 100 तत्वों के साथ 30 सरणियों के लिए यह समाधान कितना तेज है?
सहायक

यह जावास्क्रिप्ट विधियों के मूल के अलावा कुछ भी नहीं उपयोग कर रहा है, और वीएम के लिए जिसमें कोड चलेगा वह इसे अनुकूलित करने के लिए स्वतंत्र है जहां तक ​​यह कर सकता है। मैं काफी सकारात्मक हूं कि कोई भी तेजी से समाधान मौजूद नहीं है क्योंकि आप इस टिप्पणी की आयु के सापेक्ष वी 8 के आधुनिक संस्करण में इसे चला रहे हैं।
बेलफ़ोर्ड


2

मैंने एक इंटेसेशन फ़ंक्शन लिखा है जो उन वस्तुओं की विशेष संपत्ति के आधार पर ऑब्जेक्ट्स की सरणी के प्रतिच्छेदन का भी पता लगा सकता है।

उदाहरण के लिए,

if arr1 = [{id: 10}, {id: 20}]
and arr2 =  [{id: 20}, {id: 25}]

और हम चाहते हैं कि idसंपत्ति के आधार पर प्रतिच्छेदन हो , फिर आउटपुट होना चाहिए:

[{id: 20}]

जैसे, उसी के लिए फ़ंक्शन (नोट: ES6 कोड) है:

const intersect = (arr1, arr2, accessors = [v => v, v => v]) => {
    const [fn1, fn2] = accessors;
    const set = new Set(arr2.map(v => fn2(v)));
    return arr1.filter(value => set.has(fn1(value)));
};

और आप फ़ंक्शन को इस रूप में कह सकते हैं:

intersect(arr1, arr2, [elem => elem.id, elem => elem.id])

यह भी ध्यान दें: यह फ़ंक्शन चौराहे को पाता है कि पहली सरणी पर विचार प्राथमिक सरणी है और इस प्रकार चौराहे का परिणाम प्राथमिक सरणी होगा।


2

सोचें कि यह तेजी से O (array1 + array2) समय मानकर चल रहा है। map () (~) है ~ O (1)। गलत होने पर कृपया मुझे सुधारें।

const intersection = (a1, a2) => {
  let map = new Map();
  let result = []
  for (let i of a1) {
    if (!map.has(i)) map.set(i, true);
  }
  for (let i of a2) {
    if (map.has(i)) result.push(i)
  }
  return result;
}


1

यहाँ underscore.js कार्यान्वयन है:

_.intersection = function(array) {
  if (array == null) return [];
  var result = [];
  var argsLength = arguments.length;
  for (var i = 0, length = array.length; i < length; i++) {
    var item = array[i];
    if (_.contains(result, item)) continue;
    for (var j = 1; j < argsLength; j++) {
      if (!_.contains(arguments[j], item)) break;
    }
    if (j === argsLength) result.push(item);
  }
  return result;
};

स्रोत: http://underscorejs.org/docs/underscore.html#section-62


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