Как объединить два массива в JavaScript и дедублировать элементы

У меня есть два массива JavaScript:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

Я хочу, чтобы выход был:

var array3 = ["Vijendra","Singh","Shakya"];

Выходной массив должен иметь повторяющиеся слова.

Как объединить два массива в JavaScript, чтобы я получал только уникальные элементы из каждого массива в том же порядке, в котором они были вставлены в исходные массивы?

Ответы

Ответ 1

Чтобы просто объединить массивы (не удаляя дубликаты)

Версия ES5 использует Array.concat:

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];

console.log(array1.concat(array2));

Ответ 2

С Underscore.js или Lo-Dash вы можете сделать:

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>

Ответ 3

Сначала объедините два массива, затем отфильтруйте только уникальные элементы:

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]

Ответ 4

Это решение ECMAScript 6, используя оператор распространения и обобщенные массивы.

В настоящее время он работает только с Firefox и, возможно, Internet Explorer Technical Preview.

Но если вы используете Babel, вы можете получить его сейчас.

// Input: [ [1, 2, 3], [101, 2, 1, 10], [2, 1] ]
// Output: [1, 2, 3, 101, 10]
function mergeDedupe(arr)
{
  return [...new Set([].concat(...arr))];
}

Ответ 5

ES6

array1.push(...array2) // => don't remove duplication 

ИЛИ

[...array1,...array2] //   =>  don't remove duplication 

ИЛИ

[...new Set([...array1 ,...array2])]; //   => remove duplication

Ответ 6

Используя Set (ECMAScript 2015), это будет так просто:

const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = Array.from(new Set(array1.concat(array2)));

Ответ 7

Вот немного другой взгляд на петлю. С некоторыми из оптимизаций в последней версии Chrome, это самый быстрый метод для разрешения объединения двух массивов (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);
  }
}

цикл while: ~ 589 тыс. операций в секунду
фильтр: ~ 445 тыс. операций в секунду
lodash: 308 тыс. операций в секунду
для петель: 225 тыс. операций в секунду

В комментарии указывалось, что одна из моих переменных установки заставляла мой цикл опережать все остальные, потому что не нужно было инициализировать пустой массив для записи. Я согласен с этим, поэтому я переписал тест даже на игровое поле и включил еще более быстрый вариант.

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

В этом альтернативном решении я объединил решение с одним ассоциативным массивом ответов, чтобы исключить .indexOf() в цикле, который значительно замедлял работу со вторым циклом, и включил некоторые другие оптимизации, которые другие пользователи предложили в их ответы также.

Верхний ответ здесь с двойной петлей для каждого значения (i-1) все еще значительно медленнее. У lodash все еще хорошо, и я бы порекомендовал его всем, кто не против добавить библиотеку в свой проект. Для тех, кто не хочет этого, мой цикл while все еще является хорошим ответом, и ответ фильтра очень ярко демонстрирует здесь, опередив все мои тесты последней версией Canary Chrome (44.0.2360) на момент написания этой статьи.

Посмотрите ответ Майка и Дана Стокера, если вы хотите ускорить процесс. Это, безусловно, самый быстрый из всех результатов после прохождения почти всех жизнеспособных ответов.

Ответ 8

Вы можете сделать это просто с помощью ECMAScript 6,

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
  • Используйте оператор распространения для конкатенации массива.
  • Используйте Set для создания отдельного набора элементов.
  • Снова используйте оператор смены, чтобы преобразовать Set в массив.

Ответ 9

объединить два массива и удалить дубликат в 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 ]

Ответ 10

ES6 решение для объединения

let arr1 = [1,2,3,4,5];
let arr2 = [3,4,5,6];
let result = [...new Set([...arr1, ...arr2])];
console.log(result);

Ответ 11

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

Значительно лучшая функция слияния массива.

Ответ 12

Просто избегайте вложенных циклов (O (n ^ 2)) и .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);
}

Ответ 13

Просто бросаю мои два цента.

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

Это метод, который я использую много, он использует объект в качестве таблицы hashlookup для повторной проверки. Предполагая, что хэш равен O (1), то это выполняется в O (n), где n равно длине + b.length. Я честно понятия не имею, как браузер делает хэш, но он хорошо работает на многих тысячах точек данных.

Ответ 14

Почему вы не используете объект? Похоже, вы пытаетесь смоделировать набор. Однако это не будет сохранять порядок.

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
}

Ответ 15

Лучшее решение...

Вы можете проверить прямо в консоли браузера, нажав...

Без дубликата

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

Если вы хотите без дубликатов, вы можете попробовать лучшее решение здесь - Кричащий код.

[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {
    return [1, 2, 3].indexOf(el) === -1;
}));

Попробуйте в консоли браузера Chrome

 f12 > console

Выход:

["prince", "asish", 5, "ravi", 4]

[1, 2, 3, "prince"]

Ответ 16

  • Современный способ достижения этого - просто использовать оператор распространения.
  • И чтобы избежать дублирования, мы можем эффективно использовать наборы; Наборы не допускают дублирования по умолчанию.
  • Чтобы получить вывод как массив обратно из Set, мы можем использовать Array.from()

Итак, вот демонстрация для вашего сценария -

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);

Ответ 17

Упрощенный simo answer и превратил его в приятную функцию.

function mergeUnique(arr1, arr2){
    return arr1.concat(arr2.filter(function (item) {
        return arr1.indexOf(item) === -1;
    }));
}

Ответ 18

Мои полторы пенни:

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

Ответ 19

Вы можете достичь этого просто используя Underscore.js = > uniq:

array3 = _.uniq(array1.concat(array2))

console.log(array3)

Он напечатает [ "Vijendra", "Singh", "Shakya" ].

Ответ 20

Новое решение (которое использует Array.prototype.indexOf и 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 )
};

Использование:

>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])
["Vijendra", "Singh", "Shakya"]

Array.prototype.indexOf(для интернет-исследователя):

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

Ответ 21

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

Реализация метода indexOf для других браузеров взята из MDC

Ответ 22

Это можно сделать с помощью 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>

Ответ 23

Для ES6 всего одна строка:

a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))]  // [1, 2, 3, 4, 5]

Ответ 24

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

Ответ 25

array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)

Хорошая вещь об этом - производительность и что вы в целом при работе с массивами - это цепочки, такие как фильтр, карта и т.д., Чтобы вы могли добавить эту строку, и она будет конкатцировать и дедуплицировать массив2 с помощью массива1, не нуждаясь в ссылке на более позднюю один (когда вы используете методы цепочки, которых у вас нет), например:

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

(Я не люблю загрязнять Array.prototype, и это был бы единственный способ уважения к цепочке - определение новой функции нарушит ее, поэтому я думаю, что это как единственный способ добиться этого)

Ответ 26

ради этого... вот однолинейное решение:

const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()
// ['A', 'B', 'C']

Не особенно читаемый, но он может помочь кому-то:

  1. Применяет функцию уменьшения с исходным значением аккумулятора, установленным в пустой массив.
  2. Функция уменьшения использует concat для добавления каждого подматрица в массив накопителей.
  3. Результат этого передается как параметр конструктора для создания нового Set.
  4. Оператор spread используется для преобразования Set в массив.
  5. Функция sort() применяется к новому массиву.

Ответ 27

DeDuplicate single или Merge и DeDuplicate для ввода нескольких массивов. Пример ниже.

использование ES6 - установка для деструктурирования

Я написал эту простую функцию, которая принимает несколько аргументов массива. В значительной степени то же, что и решение выше, просто имеет более практичный вариант использования. Эта функция не объединяет повторяющиеся значения в один массив только для того, чтобы удалить их на более позднем этапе.

ОПРЕДЕЛЕНИЕ КОРОТКИХ ФУНКЦИЙ (всего 9 строк)

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

ИСПОЛЬЗУЙТЕ ПРИМЕР КОДЕПЕНА:

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

Ответ 28

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]

Ответ 29

Самое простое решение с фильтром:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var mergedArrayWithoutDuplicates = array1.concat(
  array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem))
);

Ответ 30

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

Обновление

См. рабочий код.

http://jsfiddle.net/UAxJa/1/