Ik heb twee JavaScript-arrays:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Ik wil dat de uitvoer is:
var array3 = ["Vijendra","Singh","Shakya"];
De uitvoerarray zou herhaalde woorden moeten hebben verwijderd.
Hoe voeg ik twee arrays in JavaScript samen zodat ik alleen de unieke items van elke array krijg in dezelfde volgorde als waarin ze in de originele arrays zijn ingevoegd?
Antwoord 1, autoriteit 100%
Om de arrays gewoon samen te voegen (zonder duplicaten te verwijderen)
ES5-versie gebruikt Array.concat
:
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
console.log(array1.concat(array2));
Antwoord 2, autoriteit 32%
Met Underscore.js of Lo-Dash kunt u het volgende doen:
console.log(_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Antwoord 3, autoriteit 18%
Voeg eerst de twee arrays samen, filter vervolgens alleen de unieke items eruit:
var a = [1, 2, 3], b = [101, 2, 1, 10]
var c = a.concat(b)
var d = c.filter((item, pos) => c.indexOf(item) === pos)
console.log(d) // d is [1, 2, 3, 101, 10]
Antwoord 4, autoriteit 14%
[...array1,...array2] // => don't remove duplication
OF
[...new Set([...array1 ,...array2])]; // => remove duplication
Antwoord 5, autoriteit 13%
Dit is een ECMAScript 6-oplossing die de spread-operator gebruikt en array-generieken.
Momenteel werkt het alleen met Firefox, en mogelijk Internet Explorer Technical Preview.
Maar als je Babel gebruikt, kun je het nu hebben.
const input = [
[1, 2, 3],
[101, 2, 1, 10],
[2, 1]
];
const mergeDedupe = (arr) => {
return [...new Set([].concat(...arr))];
}
console.log('output', mergeDedupe(input));
Antwoord 6, autoriteit 6%
Een Set gebruiken (ECMAScript 2015 ), zal het zo simpel zijn:
const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
console.log(Array.from(new Set(array1.concat(array2))));
Antwoord 7, autoriteit 2%
Hier is een iets andere kijk op de lus. Met enkele van de optimalisaties in de nieuwste versie van Chrome is dit de snelste methode om de unie van de twee arrays op te lossen (Chrome 38.0.2111).
http://jsperf.com/merge-two-arrays- alleen-unieke-waarden behouden
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [];
var arr = array1.concat(array2),
len = arr.length;
while (len--) {
var itm = arr[len];
if (array3.indexOf(itm) === -1) {
array3.unshift(itm);
}
}
terwijl-lus: ~589k ops/s
filter: ~445k ops/s
lodash: 308k ops/s
voor loops: 225k ops/s
Een opmerking wees erop dat een van mijn setup-variabelen ervoor zorgde dat mijn lus voorliep op de rest, omdat het geen lege array hoefde te initialiseren om naar te schrijven. Daar ben ik het mee eens, dus ik heb de test herschreven om het speelveld gelijk te maken, en een nog snellere optie toegevoegd.
http://jsperf.com/merge-two- arrays-keeping-only-unique-values/52
let whileLoopAlt = function (array1, array2) {
const array3 = array1.slice(0);
let len1 = array1.length;
let len2 = array2.length;
const assoc = {};
while (len1--) {
assoc[array1[len1]] = null;
}
while (len2--) {
let itm = array2[len2];
if (assoc[itm] === undefined) { // Eliminate the indexOf call
array3.push(itm);
assoc[itm] = null;
}
}
return array3;
};
In deze alternatieve oplossing heb ik de associatieve array-oplossing van één antwoord gecombineerd om de .indexOf()
-aanroep in de lus te elimineren, wat de zaken veel vertraagde met een tweede lus, en een aantal van de andere optimalisaties die andere gebruikers ook in hun antwoorden hebben voorgesteld.
Het beste antwoord hier met de dubbele lus op elke waarde (i-1) is nog steeds aanzienlijk langzamer. lodash doet het nog steeds goed, en ik zou het nog steeds aanraden aan iedereen die het niet erg vindt om een bibliotheek aan hun project toe te voegen. Voor degenen die dat niet willen, mijn while-lus is nog steeds een goed antwoord en het filterantwoord heeft hier een zeer sterke weergave, en overtreft al mijn tests met de nieuwste Canary Chrome (44.0.2360) vanaf dit moment.
Bekijk Mike’s antwoord en Het antwoord van Dan Stocker als je een tandje bij wilt zetten. Dat zijn verreweg de snelste van alle resultaten na het doornemen van bijna alle haalbare antwoorden.
Antwoord 8, autoriteit 2%
Je kunt het eenvoudig doen met ECMAScript 6,
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
- Gebruik de spread-operator om de array samen te voegen .
- Gebruik Set om een aparte set van elementen.
- Gebruik opnieuw de spread-operator om de Set om te zetten in een array.
Antwoord 9, autoriteit 2%
Ik heb het beste van dit antwoord vereenvoudigd en er een leuke functie van gemaakt:
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}
Antwoord 10
Blijf gewoon uit de buurt van geneste lussen (O(n^2)) en .indexOf()
(+O(n)).
function merge(a, b) {
var hash = {};
var i;
for (i = 0; i < a.length; i++) {
hash[a[i]] = true;
}
for (i = 0; i < b.length; i++) {
hash[b[i]] = true;
}
return Object.keys(hash);
}
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = merge(array1, array2);
console.log(array3);
Antwoord 11
Ik gooi er even mijn twee cent in.
function mergeStringArrays(a, b){
var hash = {};
var ret = [];
for(var i=0; i < a.length; i++){
var e = a[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
for(var i=0; i < b.length; i++){
var e = b[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
return ret;
}
Dit is een methode die ik veel gebruik, het gebruikt een object als een hashlookup-tabel om de dubbele controle uit te voeren. Ervan uitgaande dat de hash O(1) is, dan loopt dit in O(n) waarbij n a.length + b.length is. Ik heb eerlijk gezegd geen idee hoe de browser de hash doet, maar hij presteert goed op vele duizenden datapunten.
Antwoord 12
Array.prototype.merge = function(/* variable number of arrays */){
for(var i = 0; i < arguments.length; i++){
var array = arguments[i];
for(var j = 0; j < array.length; j++){
if(this.indexOf(array[j]) === -1) {
this.push(array[j]);
}
}
}
return this;
};
Een veel betere functie voor het samenvoegen van arrays.
Antwoord 13
BEWERKEN:
De eerste oplossing is alleen de snelste als er weinig items zijn. Als er meer dan 400 items zijn, wordt de oplossing Set
de snelste. En als er 100.000 items zijn, is het duizend keer sneller dan de eerste oplossing.
Aangezien prestaties alleen belangrijk zijn als er veel items zijn en dat de Set
-oplossing verreweg het meest leesbaar is, zou dit in de meeste gevallen de juiste oplossing moeten zijn
De onderstaande prestatieresultaten zijn berekend met een klein aantal items
Gebaseerd op jsperf, is de snelste manier (edit: als er minder dan 400 items zijn) om twee arrays samen te voegen tot een nieuwe:
for (var i = 0; i < array2.length; i++)
if (array1.indexOf(array2[i]) === -1)
array1.push(array2[i]);
Deze is 17% langzamer:
array2.forEach(v => array1.includes(v) ? null : array1.push(v));
Deze is 45% langzamer (edit: als er minder dan 100 items zijn. Het is een stuk sneller als er veel items zijn):
var a = [...new Set([...array1 ,...array2])];
En de geaccepteerde antwoorden zijn 55% langzamer (en veel langer om te schrijven) (edit: en het is enkele orde van grootte langzamer dan alle andere methoden als er 100.000 items zijn)
var a = array1.concat(array2);
for (var i = 0; i < a.length; ++i) {
for (var j = i + 1; j < a.length; ++j) {
if (a[i] === a[j])
a.splice(j--, 1);
}
}
https://jsperf.com/merge-2-arrays-without-duplicate
Antwoord 14
Waarom gebruik je geen object? Het lijkt erop dat je een set probeert te modelleren. Hierdoor blijft de bestelling echter niet behouden.
var set1 = {"Vijendra":true, "Singh":true}
var set2 = {"Singh":true, "Shakya":true}
// Merge second object into first
function merge(set1, set2){
for (var key in set2){
if (set2.hasOwnProperty(key))
set1[key] = set2[key]
}
return set1
}
merge(set1, set2)
// Create set from array
function setify(array){
var result = {}
for (var item in array){
if (array.hasOwnProperty(item))
result[array[item]] = true
}
return result
}
Antwoord 15
De beste oplossing…
U kunt rechtstreeks in de browserconsole inchecken door op…
. te klikken
Zonder duplicaat
a = [1, 2, 3];
b = [3, 2, 1, "prince"];
a.concat(b.filter(function(el) {
return a.indexOf(el) === -1;
}));
Met duplicaat
["prince", "asish", 5].concat(["ravi", 4])
Als je wilt zonder duplicaat, kun je hier een betere oplossing proberen – Schreeuwcode.
[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {
return [1, 2, 3].indexOf(el) === -1;
}));
Probeer het op de Chrome-browserconsole
f12 > console
Uitvoer:
["prince", "asish", 5, "ravi", 4]
[1, 2, 3, "prince"]
Antwoord 16
Ik weet dat deze vraag niet over een reeks objecten gaat, maar zoekers komen hier wel terecht.
het is dus de moeite waard om voor toekomstige lezers een goede ES6-manier toe te voegen voor het samenvoegen en vervolgens verwijderen van duplicaten
array van objecten:
var arr1 = [ {a: 1}, {a: 2}, {a: 3} ];
var arr2 = [ {a: 1}, {a: 2}, {a: 4} ];
var arr3 = arr1.concat(arr2.filter( ({a}) => !arr1.find(f => f.a == a) ));
// [ {a: 1}, {a: 2}, {a: 3}, {a: 4} ]
Antwoord 17
Prestaties
Vandaag 2020.10.15 voer ik tests uit op MacOs HighSierra 10.13.6 op Chrome v86, Safari v13.1.2 en Firefox v81 voor gekozen oplossingen.
Resultaten
Voor alle browsers
- oplossing H is snel/snelst
- oplossingen L is snel
- oplossing D is het snelst op chrome voor grote arrays
- oplossing G is snel op kleine arrays
- oplossing M is het langzaamst voor kleine arrays
- oplossingen E zijn het langzaamst voor grote arrays
Details
Ik voer 2 testgevallen uit:
- voor arrays met 2 elementen – u kunt het HIER
- voor arrays van 10.000 elementen – u kunt het HIER
uitvoeren
uitvoeren
over oplossingen
A,
B,
C,
D,
E,
G,
H,
J,
L,
M
weergegeven in onderstaand fragment
Antwoord 18
Voor ES6, slechts één regel:
a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))] // [1, 2, 3, 4, 5]
Antwoord 19
Mijn anderhalve cent:
Array.prototype.concat_n_dedupe = function(other_array) {
return this
.concat(other_array) // add second
.reduce(function(uniques, item) { // dedupe all
if (uniques.indexOf(item) == -1) {
uniques.push(item);
}
return uniques;
}, []);
};
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var result = array1.concat_n_dedupe(array2);
console.log(result);
Antwoord 20
U kunt dit eenvoudig bereiken met Underscore.js’s => uniq:
array3 = _.uniq(array1.concat(array2))
console.log(array3)
Het zal [“Vijendra”, “Singh”, “Shakya”] afdrukken.
Antwoord 21
Er zijn zoveel oplossingen om twee arrays samen te voegen.
Ze kunnen worden onderverdeeld in twee hoofdcategorieën (behalve het gebruik van bibliotheken van derden zoals lodash of underscore.js).
a) combineer twee arrays en verwijder dubbele items.
b) filter items uit voordat je ze combineert.
Combineer twee arrays en verwijder dubbele items
Combineren
// mutable operation(array1 is the combined array)
array1.push(...array2);
array1.unshift(...array2);
// immutable operation
const combined = array1.concat(array2);
const combined = [...array1, ...array2]; // ES6
Verenigen
Er zijn veel manieren om een array te verenigen, ik stel persoonlijk de onderstaande twee methoden voor.
// a little bit tricky
const merged = combined.filter((item, index) => combined.indexOf(item) === index);
const merged = [...new Set(combined)];
Filter items uit voordat je ze combineert
Er zijn ook veel manieren, maar ik raad persoonlijk de onderstaande code aan vanwege de eenvoud.
const merged = array1.concat(array2.filter(secItem => !array1.includes(secItem)));
Antwoord 22
Het kan gedaan worden met Set.
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2);
var tempSet = new Set(array3);
array3 = Array.from(tempSet);
//show output
document.body.querySelector("div").innerHTML = JSON.stringify(array3);
<div style="width:100%;height:4rem;line-height:4rem;background-color:steelblue;color:#DDD;text-align:center;font-family:Calibri" >
temp text
</div>
Antwoord 23
//Array.indexOf was introduced in javascript 1.6 (ECMA-262)
//We need to implement it explicitly for other browsers,
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(elt, from)
{
var len = this.length >>> 0;
for (; from < len; from++)
{
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
//now, on to the problem
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var merged = array1.concat(array2);
var t;
for(i = 0; i < merged.length; i++)
if((t = merged.indexOf(i + 1, merged[i])) != -1)
{
merged.splice(t, 1);
i--;//in case of multiple occurrences
}
Implementatie van de indexOf
-methode voor andere browsers is afkomstig van MDC
Antwoord 24
Nieuwe oplossing (die gebruikmaakt van Array.prototype.indexOf
en Array.prototype.concat
):
Array.prototype.uniqueMerge = function( a ) {
for ( var nonDuplicates = [], i = 0, l = a.length; i<l; ++i ) {
if ( this.indexOf( a[i] ) === -1 ) {
nonDuplicates.push( a[i] );
}
}
return this.concat( nonDuplicates )
};
Gebruik:
>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])
["Vijendra", "Singh", "Shakya"]
Array.prototype.indexOf (voor internet explorer):
Array.prototype.indexOf = Array.prototype.indexOf || function(elt)
{
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0) ? Math.ceil(from): Math.floor(from);
if (from < 0)from += len;
for (; from < len; from++)
{
if (from in this && this[from] === elt)return from;
}
return -1;
};
Antwoord 25
Array.prototype.add = function(b){
var a = this.concat(); // clone current object
if(!b.push || !b.length) return a; // if b is not an array, or empty, then return a unchanged
if(!a.length) return b.concat(); // if original is empty, return b
// go through all the elements of b
for(var i = 0; i < b.length; i++){
// if b's value is not in a, then add it
if(a.indexOf(b[i]) == -1) a.push(b[i]);
}
return a;
}
// Example:
console.log([1,2,3].add([3, 4, 5])); // will output [1, 2, 3, 4, 5]
Antwoord 26
array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)
Het leuke van deze is de prestatie en dat je in het algemeen, wanneer je met arrays werkt, methodes zoals filter, map, etc aan elkaar koppelt, zodat je die regel kunt toevoegen en het array2 zal concateren en dedupliceren met array1 zonder dat er een verwijzing nodig is naar de laatste (wanneer je methoden koppelt die je niet hebt), bijvoorbeeld:
someSource()
.reduce(...)
.filter(...)
.map(...)
// and now you want to concat array2 and deduplicate:
.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)
// and keep chaining stuff
.map(...)
.find(...)
// etc
(Ik hou er niet van om Array.prototype te vervuilen en dat zou de enige manier zijn om de keten te respecteren – het definiëren van een nieuwe functie zal het breken – dus ik denk dat zoiets als dit de enige manier is om dat te bereiken)
p>
Antwoord 27
Een functionele benadering met ES2015
Volgens de functionele benadering is een union
van twee Array
s slechts de samenstelling van concat
en filter
. Om optimale prestaties te leveren, gebruiken we het native gegevenstype Set
, dat is geoptimaliseerd voor het opzoeken van eigenschappen.
Hoe dan ook, de belangrijkste vraag in combinatie met een union
-functie is hoe duplicaten moeten worden behandeld. De volgende permutaties zijn mogelijk:
Array A + Array B
[unique] + [unique]
[duplicated] + [unique]
[unique] + [duplicated]
[duplicated] + [duplicated]
De eerste twee permutaties zijn gemakkelijk te verwerken met een enkele functie. De laatste twee zijn echter ingewikkelder, omdat u ze niet kunt verwerken zolang u vertrouwt op Set
-zoekopdrachten. Aangezien het overschakelen naar gewoon oude Object
eigenschapszoekopdrachten een serieuze prestatiehit zou opleveren, negeert de volgende implementatie gewoon de derde en vierde permutatie. Je zou een aparte versie van union
moeten bouwen om ze te ondersteunen.
// small, reusable auxiliary functions
const comp = f => g => x => f(g(x));
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// de-duplication
const dedupe = comp(afrom) (createSet);
// the actual union function
const union = xs => ys => {
const zs = createSet(xs);
return concat(xs) (
filter(x => zs.has(x)
? false
: zs.add(x)
) (ys));
}
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];
// here we go
console.log( "unique/unique", union(dedupe(xs)) (ys) );
console.log( "duplicated/unique", union(xs) (ys) );
Antwoord 28
DeDuplicate enkele of Merge en DeDuplicate meerdere array-ingangen. Voorbeeld hieronder.
gebruik van ES6 – Set, for of, destructuring
Ik heb deze eenvoudige functie geschreven die meerdere arrayargumenten nodig heeft.
Doet vrijwel hetzelfde als de bovenstaande oplossing, het heeft alleen meer praktische use-case. Deze functie voegt geen dubbele waarden samen tot één array, zodat ze ze in een later stadium kunnen verwijderen.
KORTE FUNCTIEDEFINITIE (slechts 9 regels)
/**
* This function merging only arrays unique values. It does not merges arrays in to array with duplicate values at any stage.
*
* @params ...args Function accept multiple array input (merges them to single array with no duplicates)
* it also can be used to filter duplicates in single array
*/
function arrayDeDuplicate(...args){
let set = new Set(); // init Set object (available as of ES6)
for(let arr of args){ // for of loops through values
arr.map((value) => { // map adds each value to Set object
set.add(value); // set.add method adds only unique values
});
}
return [...set]; // destructuring set object back to array object
// alternativly we culd use: return Array.from(set);
}
GEBRUIK VOORBEELD CODEPEN:
// SCENARIO
let a = [1,2,3,4,5,6];
let b = [4,5,6,7,8,9,10,10,10];
let c = [43,23,1,2,3];
let d = ['a','b','c','d'];
let e = ['b','c','d','e'];
// USEAGE
let uniqueArrayAll = arrayDeDuplicate(a, b, c, d, e);
let uniqueArraySingle = arrayDeDuplicate(b);
// OUTPUT
console.log(uniqueArrayAll); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 43, 23, "a", "b", "c", "d", "e"]
console.log(uniqueArraySingle); // [4, 5, 6, 7, 8, 9, 10]
Antwoord 29
Je kunt dit proberen:
const union = (a, b) => Array.from(new Set([...a, ...b]));
console.log(union(["neymar","messi"], ["ronaldo","neymar"]));
Antwoord 30
var array1 = ["one","two"];
var array2 = ["two", "three"];
var collectionOfTwoArrays = [...array1, ...array2];
var uniqueList = array => [...new Set(array)];
console.log('Collection :');
console.log(collectionOfTwoArrays);
console.log('Collection without duplicates :');
console.log(uniqueList(collectionOfTwoArrays));