J'ai deux tableaux JavaScript:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Je veux que la sortie soit:
var array3 = ["Vijendra","Singh","Shakya"];
Le tableau de sortie doit avoir les mots répétés supprimés.
Comment fusionner deux tableaux en JavaScript afin de n'obtenir que les éléments uniques de chaque tableau dans le même ordre dans lequel ils ont été insérés dans les tableaux d'origine?
Pour simplement fusionner les tableaux (sans supprimer les doublons)
Array.concat
:var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2); // Merges both arrays
// [ 'Vijendra', 'Singh', 'Singh', 'Shakya' ]
const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];
Comme il n’existe pas de méthode «intégrée» pour supprimer les doublons ( ECMA-262 a en fait Array.forEach
, ce qui serait bien pour cela), nous devons le faire manuellement:
Array.prototype.unique = function() {
var a = this.concat();
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);
}
}
return a;
};
Ensuite, pour l'utiliser:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique();
Cela préservera également l’ordre des tableaux (c’est-à-dire qu’aucun tri n’est nécessaire).
Étant donné que beaucoup de gens sont agacés par l'augmentation du prototype des boucles Array.prototype
et for in
, voici une façon moins invasive de l'utiliser:
function arrayUnique(array) {
var a = array.concat();
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);
}
}
return a;
}
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = arrayUnique(array1.concat(array2));
Pour ceux qui ont la chance de travailler avec des navigateurs sur lesquels ES5 est disponible, vous pouvez utiliser Object.defineProperty
comme ceci:
Object.defineProperty(Array.prototype, 'unique', {
enumerable: false,
configurable: false,
writable: false,
value: function() {
var a = this.concat();
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);
}
}
return a;
}
});
Avec Underscore.js ou Lo-Dash, vous pouvez effectuer les tâches suivantes:
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]
Commencez par concaténer les deux tableaux, puis filtrez uniquement les éléments uniques.
var a = [1, 2, 3], b = [101, 2, 1, 10];
var c = a.concat(b);
var d = c.filter(function (item, pos) {return c.indexOf(item) == pos});
// d is [1,2,3,101,10]
http://jsfiddle.net/simo/98622/
Comme suggéré par @Dmitry (voir le deuxième commentaire ci-dessous), une solution plus judicieuse en termes de performances serait de filtrer les éléments uniques dans b
avant de les concaténer avec a
var a = [1, 2, 3], b = [101, 2, 1, 10];
var c = a.concat(b.filter(function (item) {
return a.indexOf(item) < 0;
}));
// d is [1,2,3,101,10]
Il s’agit d’une solution ECMAScript 6 utilisant propagation des génériques d’opérateur et de tableau.
Actuellement, cela ne fonctionne qu'avec Firefox, et éventuellement avec Internet Explorer Technical Preview.
Mais si vous utilisez Babel , vous pouvez l’avoir maintenant.
// Input: [ [1, 2, 3], [101, 2, 1, 10], [2, 1] ]
// Output: [1, 2, 3, 101, 10]
function mergeDedupe(arr)
{
return [...new Set([].concat(...arr))];
}
array1.Push(...array2) // => don't remove duplication
[...array1,...array2] // => don't remove duplication
[...new Set([...array1 ,...array2])]; // => remove duplication
Avec un Set (ECMAScript 2015), ce sera aussi simple que cela:
const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = Array.from(new Set(array1.concat(array2)));
Voici une version légèrement différente de la boucle. Avec certaines des optimisations de la dernière version de Chrome, il s'agit de la méthode la plus rapide pour résoudre l'union des deux tableaux (Chrome 38.0.2111).
http://jsperf.com/merge-two-arrays-keeping-only-unique-values
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);
}
}
boucle While: ~ 589k ops/s
filtre: ~ 445k ops/s
lodash: 308k ops/s
pour les boucles: 225k op/s
Un commentaire a souligné que l'une de mes variables de configuration faisait que ma boucle devançait les autres, car elle n'avait pas besoin d'initialiser un tableau vide pour écrire. Je suis d’accord avec ça, j’ai donc réécrit le test sur un pied d’égalité et ajouté une option encore plus rapide.
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;
};
Dans cette solution alternative, j'ai combiné la solution de tableau associatif d'une réponse pour éliminer l'appel .indexOf()
de la boucle, ce qui ralentissait considérablement les choses avec une seconde boucle, et incluait certaines des autres optimisations suggérées par d'autres utilisateurs dans leurs réponses. bien.
La réponse principale ici avec la double boucle sur chaque valeur (i-1) est toujours beaucoup plus lente. lodash continue à bien se porter, et je le recommanderais quand même à quiconque ne verrait pas d'inconvénient à ajouter une bibliothèque à son projet. Pour ceux qui ne veulent pas, ma boucle while est toujours une bonne réponse et la réponse du filtre a une très bonne impression ici, battant tous mes tests avec la dernière version de Canary Chrome (44.0.2360) au moment de la rédaction de cet article.
Consultez la réponse de Mike et la réponse de Dan Stocker si vous voulez augmenter la vitesse. Ce sont de loin les résultats les plus rapides après avoir passé en revue toutes les réponses viables.
Vous pouvez le faire simplement avec ECMAScript 6,
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
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;
};
Une fonction de fusion de tableau bien meilleure.
fusionner deux tableaux et supprimer les doublons dans es6
let arr1 = [3, 5, 2, 2, 5, 5];
let arr2 = [2, 1, 66, 5];
let unique = [...new Set([...arr1,...arr2])];
console.log(unique);
// [ 3, 5, 2, 1, 66 ]
Il suffit simplement d'éviter les boucles imbriquées (O (n ^ 2)) et .indexOf()
(+ O (n)).
function merge(a, b) {
var hash = {}, 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);
}
Je viens de jeter mes deux sous.
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;
}
C’est une méthode que j’utilise beaucoup, elle utilise un objet comme table hashlookup pour effectuer la vérification des doublons. En supposant que le hachage est O (1), cela se passe dans O(n) où n est a.length + b.length. Honnêtement, je ne sais pas du tout comment le navigateur effectue le hachage, mais il fonctionne bien sur plusieurs milliers de points de données.
Pourquoi n'utilisez-vous pas un objet? On dirait que vous essayez de modéliser un ensemble. Cela ne préservera pas l'ordre, cependant.
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
}
Mon centime et demi:
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);
La meilleure solution...
Vous pouvez vérifier directement dans la console du navigateur en appuyant sur ...
a = [1, 2, 3];
b = [3, 2, 1, "prince"];
a.concat(b.filter(function(el) {
return a.indexOf(el) === -1;
}));
["prince", "asish", 5].concat(["ravi", 4])
Si vous voulez sans doublon, vous pouvez essayer une meilleure solution à partir d'ici - Shouting Code .
[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {
return [1, 2, 3].indexOf(el) === -1;
}));
Essayez sur la console du navigateur Chrome
f12 > console
Sortie:
["prince", "asish", 5, "ravi", 4]
[1, 2, 3, "prince"]
Simplifié la réponse de simo et l'a transformée en une fonction de Nice.
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}
Vous pouvez y arriver simplement en utilisant Underscore.js => uniq :
array3 = _.uniq(array1.concat(array2))
console.log(array3)
Il affichera ["Vijendra", "Singh", "Shakya"] .
//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
}
L'implémentation de la méthode indexOf
pour d'autres navigateurs provient de MDC
Cela peut être fait en utilisant 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>
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]
array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)
La bonne chose à propos de celui-ci est la performance et qu'en général, lorsque vous travaillez avec des tableaux, vous enchaînez des méthodes telles que filter, map, etc., de sorte que vous puissiez ajouter cette ligne pour concaténer et dédupliquer array2 avec array1 sans qu'il soit nécessaire de faire référence à ce dernier. un (lorsque vous chaînez des méthodes que vous n'avez pas), exemple:
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
(Je n'aime pas polluer Array.prototype et ce serait la seule façon de respecter la chaîne - la définition d'une nouvelle fonction la casserait - donc je pense qu'une telle chose est la seule façon d'accomplir cela)
Nouvelle solution (qui utilise Array.prototype.indexOf
et 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 )
};
Usage:
>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])
["Vijendra", "Singh", "Shakya"]
Array.prototype.indexOf (pour 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;
};
Pour ES6, une seule ligne:
a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))] // [1, 2, 3, 4, 5]
var arr1 = [1, 3, 5, 6];
var arr2 = [3, 6, 10, 11, 12];
arr1.concat(arr2.filter(ele => !arr1.includes(ele)));
console.log(arr1);
output :- [1, 3, 5, 6, 10, 11, 12]
pour le plaisir ... voici une solution en une seule ligne:
const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()
// ['A', 'B', 'C']
Pas particulièrement lisible mais cela peut aider quelqu'un:
Set
.Set
en un tableau.sort()
est appliquée au nouveau tableau.En suivant l’approche fonctionnelle, un union
de deux Array
s n’est que la composition de concat
et filter
. Afin de fournir des performances optimales, nous avons recours au type de données natif Set
, optimisé pour les recherches de propriété.
Quoi qu'il en soit, la question clé associée à une fonction union
est de savoir comment traiter les doublons. Les permutations suivantes sont possibles:
Array A + Array B
[unique] + [unique]
[duplicated] + [unique]
[unique] + [duplicated]
[duplicated] + [duplicated]
Les deux premières permutations sont faciles à manipuler avec une seule fonction. Cependant, les deux derniers sont plus compliqués, car vous ne pouvez pas les traiter tant que vous vous fiez à des recherches Set
. Étant donné que le passage à des recherches de propriétés Object
plaines et anciennes entraînerait des conséquences sérieuses, l’implémentation suivante ignore la troisième et la quatrième permutation. Vous devrez créer une version distincte de union
pour les prendre en charge.
// 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) );
À partir de là, il devient trivial d'implémenter une fonction unionn
, qui accepte n'importe quel nombre de tableaux (inspirés par les commentaires de naomik):
// small, reusable auxiliary functions
const uncurry = f => (a, b) => f(a) (b);
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// union and unionn
const union = xs => ys => {
const zs = createSet(xs);
return concat(xs) (
filter(x => zs.has(x)
? false
: zs.add(x)
) (ys));
}
const unionn = (head, ...tail) => foldl(union) (head) (tail);
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];
const zs = [0,1,2,3,4,5,6,7,8,9];
// here we go
console.log( unionn(xs, ys, zs) );
Il s'avère que unionn
est juste foldl
(alias Array.prototype.reduce
), qui prend union
comme réducteur. Remarque: L'implémentation n'utilisant pas d'accumulateur supplémentaire, une erreur est générée lorsque vous l'appliquez sans argument.
La méthode la plus simple consiste à utiliser concat()
pour fusionner les tableaux, puis filter()
pour supprimer les doublons, ou à utiliser concat()
, puis à placer le tableau fusionné dans un Set()
.
Première manière:
const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
//now use filter to remove dups
const removeDuplicates = mergedArray.filter((elem, index) => mergedArray.indexOf(elem) === index); // [1,2,3, 4]
Deuxième manière (mais avec des implications de performance sur l'interface utilisateur):
const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
const removeDuplicates = new Set(mergedArray);
Dans Dojo 1.6+
var unique = [];
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2); // Merged both arrays
dojo.forEach(array3, function(item) {
if (dojo.indexOf(unique, item) > -1) return;
unique.Push(item);
});
Mettre à jour
Voir le code de travail.
En supposant que les tableaux originaux ne nécessitent pas de déduplication, cela devrait être assez rapide, conserver l'ordre d'origine et ne pas modifier les tableaux d'origine ...
function arrayMerge(base, addendum){
var out = [].concat(base);
for(var i=0,len=addendum.length;i<len;i++){
if(base.indexOf(addendum[i])<0){
out.Push(addendum[i]);
}
}
return out;
}
usage:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = arrayMerge(array1, array2);
console.log(array3);
//-> [ 'Vijendra', 'Singh', 'Shakya' ]
Solution syndicale basée sur ES6
let arr1 = [1,2,3,4,5];
let arr2 = [3,4,5,6];
let result = [...new Set([...arr1, ...arr2])];
console.log(result);
Fusionner un nombre illimité de tableaux ou non-tableaux et le garder unique:
function flatMerge() {
return Array.prototype.reduce.call(arguments, function (result, current) {
if (!(current instanceof Array)) {
if (result.indexOf(current) === -1) {
result.Push(current);
}
} else {
current.forEach(function (value) {
console.log(value);
if (result.indexOf(value) === -1) {
result.Push(value);
}
});
}
return result;
}, []);
}
flatMerge([1,2,3], 4, 4, [3, 2, 1, 5], [7, 6, 8, 9], 5, [4], 2, [3, 2, 5]);
// [1, 2, 3, 4, 5, 7, 6, 8, 9]
flatMerge([1,2,3], [3, 2, 1, 5], [7, 6, 8, 9]);
// [1, 2, 3, 5, 7, 6, 8, 9]
flatMerge(1, 3, 5, 7);
// [1, 3, 5, 7]
semble que la réponse acceptée est la plus lente de mes tests;
note Je suis en train de fusionner 2 tableaux d'objets par Clé
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button type='button' onclick='doit()'>do it</button>
<script>
function doit(){
var items = [];
var items2 = [];
var itemskeys = {};
for(var i = 0; i < 10000; i++){
items.Push({K:i, C:"123"});
itemskeys[i] = i;
}
for(var i = 9000; i < 11000; i++){
items2.Push({K:i, C:"123"});
}
console.time('merge');
var res = items.slice(0);
//method1();
method0();
//method2();
console.log(res.length);
console.timeEnd('merge');
function method0(){
for(var i = 0; i < items2.length; i++){
var isok = 1;
var k = items2[i].K;
if(itemskeys[k] == null){
itemskeys[i] = res.length;
res.Push(items2[i]);
}
}
}
function method1(){
for(var i = 0; i < items2.length; i++){
var isok = 1;
var k = items2[i].K;
for(var j = 0; j < items.length; j++){
if(items[j].K == k){
isok = 0;
break;
}
}
if(isok) res.Push(items2[i]);
}
}
function method2(){
res = res.concat(items2);
for(var i = 0; i < res.length; ++i) {
for(var j = i+1; j < res.length; ++j) {
if(res[i].K === res[j].K)
res.splice(j--, 1);
}
}
}
}
</script>
</body>
</html>
La solution la plus simple avec filtre:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var mergedArrayWithoutDuplicates = array1.concat(
array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem))
);
J'ai écrit cette fonction simple qui prend plusieurs arguments de tableau . Cette fonction ne concatène pas les valeurs en double dans un seul tableau afin de pouvoir les supprimer ultérieurement.
COURTE DEFINITION DE LA FONCTION (seulement 9 lignes)
/**
* 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);
}
EXEMPLE D'UTILISATION 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]
Une autre approche pour votre examen avec réduire la fonction:
function mergeDistinct(arResult, candidate){
if (-1 == arResult.indexOf(candidate)) {
arResult.Push(candidate);
}
return arResult;
}
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var arMerge = [];
arMerge = array1.reduce(mergeDistinct, arMerge);
arMerge = array2.reduce(mergeDistinct, arMerge);//["Vijendra","Singh","Shakya"];
Ceci est simple et peut être fait en une seule ligne avec jQuery:
var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya'];
$.unique(arr1.concat(arr2))//one line
["Vijendra", "Singh", "Shakya"]
Une solution en ligne pour relier LiraNuna:
let array1 = ["Vijendra","Singh"];
let array2 = ["Singh", "Shakya"];
// Merges both arrays
let array3 = array1.concat(array2);
//REMOVE DUPLICATE
let removeDuplicate = [...new Set(array3)];
console.log(removeDuplicate);
Voici un exemple simple:
var unique = function(array) {
var unique = []
for (var i = 0; i < array.length; i += 1) {
if (unique.indexOf(array[i]) == -1) {
unique.Push(array[i])
}
}
return unique
}
var uniqueList = unique(["AAPL", "MSFT"].concat(["MSFT", "BBEP", "GE"]));
Nous définissons unique(array)
pour supprimer les éléments redondants et utilisons la fonction concat
pour combiner deux tableaux.
var MergeArrays=function(arrayOne, arrayTwo, equalityField) {
var mergeDictionary = {};
for (var i = 0; i < arrayOne.length; i++) {
mergeDictionary[arrayOne[i][equalityField]] = arrayOne[i];
}
for (var i = 0; i < arrayTwo.length; i++) {
mergeDictionary[arrayTwo[i][equalityField]] = arrayTwo[i];
}
return $.map(mergeDictionary, function (value, key) { return value });
}
En utilisant les dictionnaires et Jquery, vous pouvez fusionner les deux tableaux sans obtenir de doublons. Dans mon exemple, j'utilise un champ donné sur l'objet, mais ce pourrait être simplement l'objet lui-même.
Utiliser Lodash
La réponse de @ GijsjanB m'a parue utile, mais mes tableaux contenaient des objets comportant de nombreux attributs. J'ai donc dû les dédoublonner à l'aide de l'un des attributs.
Voici ma solution en utilisant lodash
userList1 = [{ id: 1 }, { id: 2 }, { id: 3 }]
userList2 = [{ id: 3 }, { id: 4 }, { id: 5 }]
// id 3 is repeated in both arrays
users = _.unionWith(userList1, userList2, function(a, b){ return a.id == b.id });
// users = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]
La fonction que vous transmettez au troisième paramètre a deux arguments (deux éléments) et doit renvoyer true
s’ils sont égaux.
J'ai appris un moyen peu effronté de concaténer deux tableaux avec l'opérateur de propagation:
var array1 = ['tom', 'dick', 'harry'];
var array2 = ['martin', 'ricky'];
array1.Push(...array2);
L'opérateur spread "..." divise le tableau suivant en éléments individuels, puis Push peut les traiter comme des arguments distincts.
Ceci est ma deuxième réponse, mais je crois que le plus rapide? J'aimerais que quelqu'un vérifie pour moi et réponde dans les commentaires.
Ma première tentative a touché environ 99k ops/sec et cela indique 390 ops/sec contre l'autre test jsperf de 140k (pour moi).
http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26
J'ai essayé de minimiser le plus possible les interactions entre les tableaux cette fois-ci et il semblait que je percevais des performances.
function findMerge(a1, a2) {
var len1 = a1.length;
for (var x = 0; x < a2.length; x++) {
var found = false;
for (var y = 0; y < len1; y++) {
if (a2[x] === a1[y]) {
found = true;
break;
}
}
if(!found){
a1.Push(a2.splice(x--, 1)[0]);
}
}
return a1;
}
Edit: j’ai apporté quelques modifications à ma fonction, et la performance est drastique comparée à d’autres sur le site jsperf.
Si vous ne souhaitez pas dupliquer une propriété spécifique (par exemple l'ID)
let noDuplicate = array1.filter ( i => array2.findIndex(a => i.id==a.id)==-1 );
let result = [...noDuplicate, ...array2];
Si vous souhaitez rechercher des objets uniques, utilisez JSON.stringify dans votre comparaison.
function arrayUnique(array) {
var a = array.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(JSON.stringify(a[i]) === JSON.stringify(a[j]))
a.splice(j--, 1);
}
}
return a;
}
Voici le plus efficace, en termes de temps de calcul. En outre, il conserve l'ordre initial des éléments.
Filtrez d'abord tous les doublons du deuxième tableau, puis concaténez ce qui reste au premier.
var a = [1,2,3];
var b = [5,4,3];
var c = a.concat(b.filter(function(i){
return a.indexOf(i) == -1;
}));
console.log(c); // [1, 2, 3, 5, 4]
Voici une version légèrement améliorée (plus rapide) de celle-ci, avec un inconvénient: les tableaux ne doivent pas manquer de valeurs:
var i, c = a.slice(), ci = c.length;
for(i = 0; i < b.length; i++){
if(c.indexOf(b[i]) == -1)
c[ci++] = b[i];
}
Array.prototype.union = function (other_array) {
/* you can include a test to check whether other_array really is an array */
other_array.forEach(function(v) { if(this.indexOf(v) === -1) {this.Push(v);}}, this);
}
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));
- Une méthode moderne pour y parvenir consiste simplement à utiliser le OP&EACUTE;RATEUR DE PROPAGATION.
- Et pour éviter les doublons, nous pouvons utiliser efficacement SETS; Les ensembles ne permettent pas les doublons par défaut.
- Pour obtenir une sortie sous forme de tableau à partir d'un Set, nous pouvons utiliser ARRAY.FROM ()
Alors, voici une démonstration de votre scénario -
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);
Vous pouvez l'utiliser comme union(array1, array2, array3, ...)
/**
* Merges two or more arrays keeping unique items. This method does
* not change the existing arrays, but instead returns a new array.
*/
function union<T>(...arrays: T[]) {
return [...new Set([...arrays].flat())];
}
Il s'agit de ES2019 en raison de la fonction flat()
, mais vous pouvez utiliser core-js pour l'obtenir sous forme de fichier polyfill. Le T
ici est un type générique TypeScript, que vous pouvez supprimer si vous n'utilisez pas TypeScript. Si vous utilisez TypeScript, veillez à ajouter "lib": ["es2019.array"]
aux options du compilateur dans tsconfig.json
.
utilisez simplement lodash _. union
Cela pourrait être réalisé en composant deux fonctions essentielles.
const getUniqueMerge = (...arrs) => getUniqueArr(mergeArrs(...arrs))
const getUniqueArr = (array) => Array.from(new Set(array))
const mergeArrs = (...arrs) => [].concat(...arrs)
Il peut gérer un nombre illimité de tableaux ou de valeurs
console.log(getUniqueMerge(["Vijendra","Singh"],["Singh", "Shakya"])
// ["Vijendra", "Singh", "Shakya"]
console.log(getUniqueMerge(["Sheldon", "Cooper"], ["and", "Cooper", "Amy", "and"], "Farrah", "Amy", "Fowler"))
// ["Sheldon", "Cooper", "and", "Amy", "Farrah", "Fowler"]
Je pense que cela fonctionne plus vite.
removeDup = a => {
for (let i = a.length - 1; i >= 0; i--) {
for (let j = i-1; j >= 0; j--) {
if (a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
Si, comme moi, vous devez prendre en charge les anciens navigateurs, cela fonctionne avec IE6 +.
function es3Merge(a, b) {
var hash = {},
i = (a = a.slice(0)).length,
e;
while (i--) {
hash[a[i]] = 1;
}
for (i = 0; i < b.length; i++) {
hash[e = b[i]] || a.Push(e);
}
return a;
};
http://jsperf.com/merge-two-arrays-keeping-only-unique-values/22
Voici ma solution https://Gist.github.com/4692150 avec un résultat égal et simple à utiliser:
function merge_arrays(arr1,arr2)
{
...
return {first:firstPart,common:commonString,second:secondPart,full:finalString};
}
console.log(merge_arrays(
[
[1,"10:55"] ,
[2,"10:55"] ,
[3,"10:55"]
],[
[3,"10:55"] ,
[4,"10:55"] ,
[5,"10:55"]
]).second);
result:
[
[4,"10:55"] ,
[5,"10:55"]
]
Vous pouvez essayer ceci:
const union = (a, b) => Array.from(new Set([...a, ...b]));
console.log(union(["neymar","messi"], ["ronaldo","neymar"]));
Array.prototype.pushUnique = function(values)
{
for (var i=0; i < values.length; i++)
if (this.indexOf(values[i]) == -1)
this.Push(values[i]);
};
Essayer:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
array1.pushUnique(array2);
alert(array1.toString()); // Output: Vijendra,Singh,Shakya
Utilisation: https://Gist.github.com/samad-aghaei/7250ffb74ed80732debb1cbb14d2bfb0
var _uniqueMerge = function(opts, _ref){
for(var key in _ref)
if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object)
_ref[key] = _uniqueMerge((opts ? opts[key] : null), _ref[key] );
else if(opts && opts.hasOwnProperty(key))
_ref[key] = opts[key];
else _ref[key] = _ref[key][1];
return _ref;
}
Si vous utilisez uniquement underscore.js, il n'a pas unionWith, unionBy
vous pouvez essayer: _.uniq(_.union(arr1, arr2), (obj) => obj.key)
(key est le paramètre clé de chaque objet) Cela devrait aider à devenir unique après l'union des deux tableaux.
Juste écrit avant pour la même raison (fonctionne avec n'importe quel nombre de tableaux):
/**
* Returns with the union of the given arrays.
*
* @param Any amount of arrays to be united.
* @returns {array} The union array.
*/
function uniteArrays()
{
var union = [];
for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
{
eachArgument = arguments[argumentIndex];
if (typeof eachArgument !== 'array')
{
eachArray = eachArgument;
for (var index = 0; index < eachArray.length; index++)
{
eachValue = eachArray[index];
if (arrayHasValue(union, eachValue) == false)
union.Push(eachValue);
}
}
}
return union;
}
function arrayHasValue(array, value)
{ return array.indexOf(value) != -1; }
La meilleure et la plus simple consiste à utiliser la fonction "some ()" de JavaScript qui renvoie true ou false indiquant si le tableau contient l'élément de l'objet. Vous pouvez faire ceci:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1;
array2.forEach(function(elementArray2){
var isEquals = array1.some(function(elementArray1){
return elementArray1 === elementArray2;
})
if(!isEquals){
array3.Push(elementArray2);
}
});
console.log(array3);
Les resultats:
["Vijendra", "Singh", "Shakya"]
ss vous le souhaitez ... sans le dupliquer ...