Paprasčiausias kodas masyvo kirtimui javascript'e

Kas yra lengviausias, nemokamai bibliotekos kodui įgyvendinti masyvų sankirtą javascript? Noriu parašyti

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

ir gaukite

 [2, 3] 
356
11 дек. Petras yra gruodžio 11 d. 2009-12-11 06:04 '09, 6:04 val. 2009-12-11 06:04
@ 35 atsakymai
  • 1
  • 2

Naudokite kombinaciją Array.prototype.filter ir Array.prototype.indexOf .

 array1.filter(function(n) { return array2.indexOf(n) !== -1; }); 
675
atsakymas pateikiamas anon. Gruodžio 11 d 2009-12-11 06:08 '09, 06:08 am. 2009-12-11 06:08

Atrodo, kad „destruktyvus“ yra paprasčiausias, ypač jei galime manyti, kad įvestis yra rūšiuojama:

  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  { result.push(a.shift()); b.shift(); } } return result; } 
border=0

Neardomieji procesai turi būti sudėtingesni, nes turime stebėti rodiklius:

  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  { result.push(a[ai]); ai++; bi++; } } return result; } 
149
11 дек. atsakymas pateikiamas atk 11 d. 2009-12-11 06:45 '09 6:45 am 2009-12-11 06:45

Jei jūsų aplinka palaiko „ ECMAScript 6“ rinkinį , vienas paprastas ir tariamai efektyvus būdas (žr. Specifikacijos nuorodą):

 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); } 

Trumpesnis, bet mažiau suprantamas (taip pat nesukuriant papildomos „ Set sankirtos):

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

Atkreipkite dėmesį, kad rinkinio įgyvendinimas leis tik unikalias vertes, todėl apskaičiuota, kad new Set[1,2,3,3].size bus 3 .

28
05 мая '16 в 6:21 2016-05-05 06:21 atsakymą pateikė nbarbosa 05 gegužės 16 d. 6:21 2016-05-05 06:21

Naudojant „ Underscore.js“

 _.intersection( [0,345,324] , [1,0,324] ) // gives [0,324] 
17
29 сент. Atsakymą Sai Ram pateikė rugsėjo 29 d 2016-09-29 10:51 '16 at 10:51 am 2016-09-29 10:51

Naudojant jQuery :

 var a = [1,2,3]; var b = [2,3,4,5]; var c = $(b).not($(b).not(a)); alert(c); 
11
25 дек. atsakymą pateikė Gowsikan 25 d. 2013-12-25 10:20 '13, 10:20, 2013-12-25 10:20

Kaip lengva naudoti asociatyvias matricas?

 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; } 

pakeisti:

 // 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; } 
10
11 дек. Atsakymą pateikė Steven Huwig, gruodžio 11 d. 2009-12-11 07:22 '09 7:22 AM 2009-12-11 07:22

Įgyvendinant „@atk“ įgyvendinimą rūšiuojamiems primityviems masyvams galima pagerinti .pop, o ne .shift.

 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  { result.push(a.pop()); b.pop(); aLast--; bLast--; } } return result; } 

Aš sukūriau testą naudojant jsPerf: http://bit.ly/P9FrZK . Tai yra maždaug tris kartus greičiau naudoti .pop.

8
atsakymas pateikiamas xn. 2012-07-19 22:33 Liepos 19, 12 d., 10:33 val. 2012-07-19 22:33

Masyvams, kuriuose yra tik eilutės ar skaičiai, galite ką nors padaryti su rūšiavimu, kaip ir kiti atsakymai. Apskritai atsitiktinių objektų masyvų atveju, nemanau, kad galite išvengti ilgos trasos. Toliau pateikiamas bet kokio masyvų, pateiktų kaip parametrai, arrayIntersection pagal 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"]; 
7
11 дек. Atsakymą pateikė Tim Down 11 Dec 2009-12-11 14:37 '09 ne 14:37 2009-12-11 14:37

Mano indėlis į ES6 sąlygas. Apskritai, jis nustato masyvo susikirtimą su neapibrėžtu skaičiumi masyvų, pateiktų kaip argumentai.

7
15 мая '16 в 15:23 2016-05-15 15:23 atsakymas pateikiamas Redu gegužės 15 d., 16 val. 15:23 2016-05-15 15:23

Tai yra gana trumpas naudojant ES2015 ir rinkinius. Priima tipo Array vertes, pvz., Eilutes, ir pašalina dublikatus.

6
12 мая '17 в 11:59 2017-05-12 11:59 Atsakymą pateikė SeregPie gegužės 12 d. 17 val. 11:59 2017-05-12 11:59
  • Rūšiuoti
  • patikrinkite po vieną iš 0 indekso, sukurkite naują masyvą.

Kažkas panašaus.

 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])); 

PS: algoritmas, skirtas tik numeriams ir normalioms eilutėms, arbino objektų masyvų sankirtos gali neveikti.

6
11 дек. Atsakymas jums duotas 11 gruodis. 2009-12-11 06:15 '09 6:15 am 2009-12-11 06:15

Nedidelis nustatymas mažiausiam čia ( filtras / indexOf sprendimas ), būtent vertybių indekso kūrimas vienoje iš masyvų, naudojant „JavaScript“ objektą, sumažina jį nuo O (N * M) iki „tikriausiai“ linijinio laiko. source1 šaltinis2

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

Tai nėra paprasčiausias sprendimas (tai daugiau kodo, nei filtras + indexOf ), ir tai nėra greičiausias (galbūt lėtesnis nei pastovus faktorius nei intersect_safe () ), tačiau atrodo, kad tai gana gera pusiausvyra. Ji yra labai paprasta, tuo pačiu užtikrindama gerus rezultatus ir nereikalaudama iš anksto surūšiuotų įėjimų.

5
26 нояб. Atsakykite Dovydui lapkričio 26 d 2015-11-26 21:46 '15 - 21:46 2015-11-26 21:46

Su tam tikrais duomenų apribojimais galite tai padaryti tiesiniu laiku!

Teigiamiems sveikiesiems skaičiams : naudokite masyvą, kuris suskirsto reikšmes į „matomas / nepastebėtas“ logines.

 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; } 

Objektams taikomas panašus metodas: paimkite manekeno raktą, nustatykite jį į „true“ kiekvienam 1 masyvo elementui, tada suraskite raktą masyvo2 elementuose. Išvalykite, kai baigsite.

 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; } 

Žinoma, jūs turite būti tikri, kad raktas nepasirodė anksčiau, kitaip jūs sunaikinsite savo duomenis ...

4
16 июля '15 в 19:13 2015-07-16 19:13 atsakymas duotas tarulenui liepos 16, 15, 19:13 2015-07-16 19:13

Kitas indeksuotas metodas, kuris gali apdoroti bet kokį masyvų skaičių vienu metu:

 // 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; }; 

Jis veikia tik toms vertėms, kurias galima vertinti kaip eilutes, ir turite jas perduoti kaip masyvą, pavyzdžiui:

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

... tačiau jis priima objektus skaidriai kaip parametrą arba kaip bet kurį elementą, kuris susikerta (visada grąžina bendrų vertybių masyvą). Pavyzdžiai:

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

EDIT: Aš tik pastebėjau, kad tai tam tikra prasme šiek tiek buggy.

Tai yra: Aš jį užkodavau, manydamas, kad įvesties matricos negali turėti pakartojimų (kaip neparodyta pavyzdyje).

Bet jei įvesties matricos susideda iš pakartojimų, tai sukels neteisingus rezultatus. Pavyzdys (naudojant toliau pateiktą įgyvendinimą):

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

Laimei, tai lengvai nustatoma tiesiog pridedant antro lygio indeksą. Tai yra:

Redaguoti:

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

pateikė:

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

... ir:

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

pateikė:

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

Visas pavyzdys:

 // 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' ] 
4
04 марта '15 в 15:51 2015-03-04 15:51 atsakymas pateikiamas bitifet 04 kovo 15 d. 15:51 2015-03-04 15:51

Aš prisidėsiu prie to, kas geriausia man:

 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; }; } 
3
18 мая '13 в 16:36 2013-05-18 16:36 Atsakymą pateikė Johanas , gegužės 18 d., 13 d., 4:36, 2013-05-18 16:36

https://jsperf.com/array-intersection- palyginimą, skirtą veiklos rezultatų palyginimui. 

 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 
  • Ops / sek mažose matricose (100 elementų):

    3
  • 06 мая '17 в 15:34 2017-05-06 15:34 atsakymas pateikiamas le_m 06 gegužės 17 d., 15:34 2017-05-06 15:34
     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; } 
    3
    20 сент. atsakymą pateikė Gabe rugsėjo 20 d 2012-09-20 00:13 '12 0:13 2012-09-20 00:13

    „indexOf“, skirtas IE 9.0, chromui, firefox, operai,

      function intersection(a,b){ var rs = [], x = a.length; while (x--) b.indexOf(a[x])!=-1  rs.push(a[x]); return rs.sort(); } intersection([1,2,3], [2,3,4,5]); //Result: [2,3] 
    3
    28 окт. Martin Roberto Mondragon atsakymas Sotel Oct 28 2014-10-28 20:08 „14, 20:08 2014-10-28 20:08

    2
    03 окт. Atsakymas pateikiamas Vlad Bezden 03 okt. 2016-10-03 22:51 '16 at 10:51 pm 2016-10-03 22:51

    Dėl paprastumo:

     // 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] 

    Privalumai:

    • paprastas purvas
    • orientuotas į duomenis
    • veikia bet kokiam sąrašų skaičiui
    • veikia savavališkai sąrašo ilgiams
    • veikia savavališkiems vertės tipams
    • veikia savavališkai
    • išsaugo formą (pirmojo pasirodymo tvarka bet kuriame masyve)
    • išeiti anksti
    • saugi atmintis, išskyrus funkcijų / masyvo prototipų klastojimą.

    Trūkumai:

    • didesnis atminties naudojimas
    • didesnė procesoriaus apkrova
    • reikalauja supratimo apie sumažinimą
    • reikia suprasti duomenų srautą

    Jūs nenorite, kad tai dirbtumėte su 3D varikliu ar branduoliu, bet jei kyla problemų paleidžiant ją įvykio pagrindu, jūsų dizainas turės didelių problemų.

    2
    02 февр. Atsakymą pateikė Norguard 02 vasaris. 2017-02-02 23:22 '17, 23:22 pm 2017-02-02 23:22

    Funkcinis požiūris su ES2015

    Funkciniu požiūriu turėtų būti atsižvelgiama į grynų funkcijų naudojimą be šalutinio poveikio, kurių kiekviena susijusi tik su viena užduotimi.

    Šie apribojimai didina susijusių funkcijų gebėjimą ir pakartotinį panaudojimą.

    2
    11 окт. Atsakymas pateikiamas 11- osios sesijos metu . 2016-10-11 12:07 '16 at 12:07 2016-10-11 12:07
     function getIntersection(arr1, arr2){ var result = []; arr1.forEach(function(elem){ arr2.forEach(function(elem2){ if(elem === elem2){ result.push(elem); } }); }); return result; } getIntersection([1,2,3], [2,3,4,5]); // [ 2, 3 ] 
    1
    21 окт. atsakymas duotas bekzat Spalio 21 d 2017-10-21 02:36 '17, 02:36, 2017-10-21 02:36

    .reduce sukurti žemėlapį ir .filter kad rastumėte sankirtą. delete .filter leidžiame antrąjį masyvą apdoroti kaip unikalią.

     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; }); } 

    Manau, kad toks požiūris yra gana paprastas. Jis dirba pastoviu laiku.

    1
    21 марта '17 в 12:19 2017-03-21 12:19 atsakymas suteiktas Beldenui kovo 21 d. 17 val. 12:19 2017-03-21 12:19

    Štai „ underscore.js“ įgyvendinimas:

     _.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; }; 

    Šaltinis: http://underscorejs.org/docs/underscore.html#section-62

    1
    30 дек. Atsakymas duotas Dorian 30 d. 2014-12-30 03:58 '15 at 3:58 2014-12-30 03:58

    Tai turbūt paprasčiausias, išskyrus list1.filter (n => list2.includes (n))

    1
    03 февр. atsakymas, kurį pateikė Chris Lwin 03 vasaris 2018-02-03 07:55 '18 at 7:55 2018-02-03 07:55
     var listA = [1,2,3,4,5,6,7]; var listB = [2,4,6,8]; var result = listA.filter(itemA=> { return listB.some(itemB => itemB === itemA); }); 
    0
    24 янв. atsakymas, kurį pateikė jcmordan Jan 24 2017-01-24 22:12 '17 ne 10:12 2017-01-24 22:12

    Šis kodas taip pat pašalina dublikatus:

      function intersect(x, y) { if (y.length > x.length) temp = y, y = x, x= temp; return x.filter(function (e, i, c) { return c.indexOf(e) === i; }); } 
    0
    01 дек. Atsakymas duotas Eni gruodžio 1 d. 2017-12-01 16:55 '17 at 4:55 2017-12-01 16:55

    Tikiuosi, kad tai padės visoms versijoms.

     function diffArray(arr1, arr2) { var newArr = []; var large = arr1.length>=arr2.length?arr1:arr2; var small = JSON.stringify(large) == JSON.stringify(arr1)?arr2:arr1; for(var i=0;i<large.length;i++){ var copyExists = false; for(var j =0;j<small.length;j++){ if(large[i]==small[j]){ copyExists= true; break; } } if(!copyExists) { newArr.push(large[i]); } } for(var i=0;i<small.length;i++){ var copyExists = false; for(var j =0;j<large.length;j++){ if(large[j]==small[i]){ copyExists= true; break; } } if(!copyExists) { newArr.push(small[i]); } } return newArr; } 
    0
    29 янв. Shubham Pandey atsakymas sausio 29 d 2017-01-29 17:14 '17 17:14 pm 2017-01-29 17:14

    Remiantis puikiu „Anon“ atsakymu, jis grąžina dviejų ar daugiau masyvų sankirtą.

     function arrayIntersect(arrayOfArrays) { var arrayCopy = arrayOfArrays.slice(), baseArray = arrayCopy.pop(); return baseArray.filter(function(item) { return arrayCopy.every(function(itemList) { return itemList.indexOf(item) !== -1; }); }); } 
    0
    26 янв. Atsakymą pateikė Dag Sondre Hansen sausio 26 d. 2017-01-26 11:54 '17 at 11:54 2017-01-26 11:54

    Aš išplėčiau taruleno atsakymą, kad galėčiau dirbti su bet kokiu masyvų skaičiumi. Ji taip pat turėtų dirbti su ne sveikaisiais skaičiais.

     function intersect() { const last = arguments.length - 1; var seen={}; var result=[]; for (var i = 0; i < last; i++) { for (var j = 0; j < arguments[i].length; j++) { if (seen[arguments[i][j]]) { seen[arguments[i][j]] += 1; } else if (!i) { seen[arguments[i][j]] = 1; } } } for (var i = 0; i < arguments[last].length; i++) { if ( seen[arguments[last][i]] === last) result.push(arguments[last][i]); } return result; } 
    0
    19 сент. atsakymas pateikiamas gabe appleton rugsėjo 19 d 2016-09-19 17:34 '16 at 17:34 pm 2016-09-19 17:34
    • 1
    • 2