Ich habe mehrere Arrays mit String-Werten und möchte diese miteinander vergleichen und nur die übereinstimmenden Ergebnisse beibehalten, die zwischenALLvon ihnen identisch sind.
In Anbetracht dieses Beispielcodes:
var arr1 = ['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'Apple', 'pizza'];
var arr3 = ['banana', 'pizza', 'fish', 'Apple'];
Ich möchte das folgende Array erstellen, das Übereinstimmungen aus allen angegebenen Arrays enthält:
['Apple', 'fish', 'pizza']
Ich weiß, dass ich alle Arrays mit var newArr = arr1.concat(arr2, arr3);
kombinieren kann, aber das gibt mir nur ein Array mit allem plus den Duplikaten. Kann dies leicht gemacht werden, ohne dass der Aufwand für Bibliotheken wie underscore.js erforderlich ist?
(Großartig, und jetzt Ich habe auch Hunger!)
EDITIch sollte erwähnen, dass es eine unbekannte Anzahl von Arrays geben könnte, ich habe nur 3 als Beispiel verwendet.
var result = arrays.shift().filter(function(v) {
return arrays.every(function(a) {
return a.indexOf(v) !== -1;
});
});
DEMO:http://jsfiddle.net/nWjcp/2/
Sie können zuerst das äußere Array sortieren, um das kürzeste Array am Anfang zu erhalten ...
arrays.sort(function(a, b) {
return a.length - b.length;
});
Der Vollständigkeit halber sei hier eine Lösung angegeben, die Duplikate in den Arrays behandelt. Es verwendet .reduce()
anstelle von .filter()
...
var result = arrays.shift().reduce(function(res, v) {
if (res.indexOf(v) === -1 && arrays.every(function(a) {
return a.indexOf(v) !== -1;
})) res.Push(v);
return res;
}, []);
Nun, da Sie der Frage eine unbestimmte Anzahl von Arrays hinzugefügt haben, wird hier ein weiterer Ansatz verwendet, bei dem die Anzahl der einzelnen Elemente in einem Objekt erfasst und dann die Elemente mit der maximalen Anzahl sortiert werden.
Vorteile dieses Ansatzes:
Und hier ist der Code:
function containsAll(/* pass all arrays here */) {
var output = [];
var cntObj = {};
var array, item, cnt;
// for each array passed as an argument to the function
for (var i = 0; i < arguments.length; i++) {
array = arguments[i];
// for each element in the array
for (var j = 0; j < array.length; j++) {
item = "-" + array[j];
cnt = cntObj[item] || 0;
// if cnt is exactly the number of previous arrays,
// then increment by one so we count only one per array
if (cnt == i) {
cntObj[item] = cnt + 1;
}
}
}
// now collect all results that are in all arrays
for (item in cntObj) {
if (cntObj.hasOwnProperty(item) && cntObj[item] === arguments.length) {
output.Push(item.substring(1));
}
}
return(output);
}
Arbeitsdemo: http://jsfiddle.net/jfriend00/52mAP/
Zu Ihrer Information, dies erfordert kein ES5 und funktioniert daher in allen Browsern ohne Shim.
In einem Leistungstest für 15 Arrays mit einer Länge von je 1000 war dies mehr als zehnmal schneller als die Suchmethode, die in dieser Jsperf-Antwort verwendet wurde: http://jsperf.com/in-all-arrays .
Hier ist eine Version, die eine ES6 Map
und Set
verwendet, um die Anzahl zu bestimmen und zu verfolgen. Dies hat den Vorteil, dass der Datentyp erhalten bleibt und beliebig sein kann (er muss nicht einmal eine natürliche String-Konvertierung haben. Die Daten können sogar Objekte sein, obwohl Objekte verglichen werden, weil sie genau das gleiche Objekt sind und nicht das gleiche haben Eigenschaften/Werte).
var arrays = [
['valueOf', 'toString','Apple', 'orange', 'banana', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza', 1, 2, 999, 888],
['valueOf', 'toString','taco', 'fish', 'fish', 'Apple', 'pizza', 1, 999, 777, 999, 1],
['valueOf', 'toString','banana', 'pizza', 'fish', 'Apple', 'Apple', 1, 2, 999, 666, 555]
];
// subclass for updating cnts
class MapCnt extends Map {
constructor(iterable) {
super(iterable);
}
cnt(iterable) {
// make sure items from the array are unique
let set = new Set(iterable);
// now update the cnt for each item in the set
for (let item of set) {
let cnt = this.get(item) || 0;
++cnt;
this.set(item, cnt);
}
}
}
function containsAll(...allArrays) {
let cntObj = new MapCnt();
for (array of allArrays) {
cntObj.cnt(array);
}
// now see how many items have the full cnt
let output = [];
for (var [item, cnt] of cntObj.entries()) {
if (cnt === allArrays.length) {
output.Push(item);
}
}
return(output);
}
var result = containsAll.apply(this, arrays);
document.body.innerHTML = "<pre>[<br> " + result.join(',<br> ') + "<br>]</pre>";
Angenommen, es gibt ein Array von Arrays, von denen wir den Schnittpunkt finden möchten, könnte der einfachste Ansatz für einen einzelnen Liner sein
var arr = [[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8],[4,5,6,7]],
int = arr.reduce((p,c) => p.filter(e => c.includes(e)));
document.write("<pre>" + JSON.stringify(int) + "</pre>");
Ein paar Gedanken - Sie können nur die Elemente im kürzesten Array Vergleichen und Duplikate im zurückgegebenen Array vermeiden.
function arraysInCommon(arrays){
var i, common,
L= arrays.length, min= Infinity;
while(L){
if(arrays[--L].length<min){
min= arrays[L].length;
i= L;
}
}
common= arrays.splice(i, 1)[0];
return common.filter(function(itm, indx){
if(common.indexOf(itm)== indx){
return arrays.every(function(arr){
return arr.indexOf(itm)!= -1;
});
}
});
}
var arr1= ['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2= ['taco', 'fish', 'Apple', 'pizza', 'Apple','Apple'];
var arr3= ['banana', 'pizza', 'fish', 'Apple','fish'];
var allArrays = [arr1,arr2,arr3];
arraysInCommon(allArrays).sort();
rückgabewert: Apple,fish,pizza
DEMO - http://jsfiddle.net/kMcud/
Hier geht es um eine einzeilige Lösung. Sie können es in zwei Denkschritte aufteilen:
var arrA = [1,2,3,4,5];
var arrB = [4,5,10];
var innerJoin = arrA.filter(el=>arrB.includes(el));
console.log(`Intersection is: ${innerJoin}`);
var arrays = [
['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'],
['taco', 'fish', 'Apple', 'pizza'],
['banana', 'pizza', 'fish', 'Apple']
];
var join = arrays.reduce((join, current) => join.filter(el => current.includes(el)));
console.log(`Intersection is: ${join}`);
Array von Arrays annehmen und alle Arrays durchsehen:
DEMO: http://jsfiddle.net/qUQHW/
var tmp = {};
for (i = 0; i < data.length; i++) {
for (j = 0; j < data[i].length; j++) {
if (!tmp[data[i][j]]) {
tmp[data[i][j]] = 0;
}
tmp[data[i][j]]++;
}
}
var results = $.map(tmp, function(val,key) {
return val == data.length ? key :null;
})
Dies sollte für eine beliebige Anzahl von Arrays funktionieren:
function intersection(arr1, arr2) {
var temp = [];
for (var i in arr1) {
var element = arr1[i];
if (arr2.indexOf(element) > -1) {
temp.Push(element);
}
}
return temp;
}
function multi_intersect() {
var arrays = Array.prototype.slice.apply(arguments).slice(1);
var temp = arguments[0];
for (var i in arrays) {
temp = intersection(arrays[i], temp);
if (temp == []) {
break;
}
}
return temp;
}
var arr1 = ['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'Apple', 'pizza'];
var arr3 = ['banana', 'pizza', 'fish', 'Apple'];
multi_intersect(arr1, arr2, arr3);
Dies ist im Wesentlichen eine Zusammenstellung aller niedergeschlagenen Antworten:
// Intersect any number of arrays:
function intersect() {
// - Arguments -> traditional array,
// - First item ( arrays[0] ) = shortest to reduce iterations
var arrays = Array.prototype.slice.call(arguments).sort(function(a, b) {
return a.length - b.length;
});
// Use first array[0] as the base.
var a = arrays.shift();
var result = [];
for (var i = a.length; i--;) {
var val = a[i];
// Prevent duplicates
if (result.indexOf(val) < 0) {
// Seek
var found = true;
for (var ii = arrays.length; ii--;) {
if (arrays[ii].indexOf(val) < 0) {
found = false;
break;
}
}
if (found) {
result.Push(val);
}
}
}
return result;
}
/*
// Slower, but smaller code-base:
function intersect (){
// - Arguments -> traditional array,
// - First item ( arrays[0] ) = shortest to reduce iterations
var arrays = Array.prototype.slice.call(arguments).sort(function(a, b) {
return a.length - b.length;
});
// Use first array[0] as the base.
var a = arrays.shift();
return a.filter(function (val, idx, aa) {
// Seek
for(var i=arrays.length; i--;){
if (arrays[i].indexOf(val) < 0) {
return false;
}
}
// Prevent duplicates
return aa.indexOf(val) === idx;
});
}
*/
var arr1 = ['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'Apple', 'pizza', 'Apple', 'Apple'];
var arr3 = ['banana', 'pizza', 'fish', 'Apple', 'fish'];
var arr1 = ['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'];
var arr2 = ['taco', 'fish', 'Apple', 'pizza', 'Apple', 'Apple'];
var arr3 = ['banana', 'pizza', 'fish', 'Apple', 'fish'];
var result = intersect(arr1, arr2, arr3);
// For fiddle output:
var elem = document.getElementById("result");
elem.innerHTML = JSON.stringify(result);
console.log(result);
<div id="result">Results</div>
Nur um das Ganze zu verdeutlichen, ein weiterer Ansatz mit langen Händen:
function getCommon(a) {
// default result is copy of first array
var result = a[0].slice();
var mem, arr, found = false;
// For each member of result, see if it's in all other arrays
// Go backwards so can splice missing entries
var i = result.length;
while (i--) {
mem = result[i];
// Check in each array
for (var j=1, jLen=a.length; j<jLen; j++) {
arr = a[j];
found = false;
// For each member of arr and until found
var k = arr.length;
while (k-- && !found) {
// If found in this array, set found to true
if (mem == arr[k]) {
found = true;
}
}
// if Word wasn't found in this array, remove it from result and
// start on next member of result, skip remaining arrays.
if (!found) {
result.splice(i,1);
break;
}
}
}
return result;
}
var data = [
['taco', 'fish', 'Apple', 'pizza', 'mango', 'pear'],
['Apple', 'orange', 'banana', 'pear', 'fish', 'pancake', 'taco', 'pizza'],
['banana', 'pizza', 'fish', 'Apple'],
['banana', 'pizza', 'fish', 'Apple', 'mango', 'pear']
];
Funktion zum Auffinden nie aufzuzählender Eigenschaften basierend auf diesem Objekt in Object.prototype:
// Return an array of Object.prototype property names that are not enumerable
// even when added directly to an object.
// Can be helpful with IE as properties like toString are not enumerable even
// when added to an object.
function getNeverEnumerables() {
// List of Object.prototype property names plus a random name for testing
var spNames = 'constructor toString toLocaleString valueOf ' +
'hasOwnProperty isPrototypeOf propertyIsEnumerable foo';
var spObj = {foo:'', 'constructor':'', 'toString':'', 'toLocaleString':'', 'valueOf':'',
'hasOwnProperty':'', 'isPrototypeOf':'', 'propertyIsEnumerable':''};
var re = [];
// BUild list of enumerable names in spObj
for (var p in spObj) {
re.Push(p);
}
// Remove enumerable names from spNames and turn into an array
re = new RegExp('(^|\\s)' + re.join('|') + '(\\s|$)','g');
return spNames.replace(re, ' ').replace(/(^\s+)|\s\s+|(\s+$)/g,'').split(' ');
}
document.write(getNeverEnumerables().join('<br>'));