Ответ 1
Чтобы просто объединить массивы (не удаляя дубликаты)
Версия ES5 использует Array.concat
:
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
console.log(array1.concat(array2));
У меня есть два массива JavaScript:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Я хочу, чтобы выход был:
var array3 = ["Vijendra","Singh","Shakya"];
Выходной массив должен иметь повторяющиеся слова.
Как объединить два массива в JavaScript, чтобы я получал только уникальные элементы из каждого массива в том же порядке, в котором они были вставлены в исходные массивы?
Чтобы просто объединить массивы (не удаляя дубликаты)
Array.concat
:
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
console.log(array1.concat(array2));
С 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>
Сначала объедините два массива, затем отфильтруйте только уникальные элементы:
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]
Это решение 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))];
}
array1.push(...array2) // => don't remove duplication
[...array1,...array2] // => don't remove duplication
[...new Set([...array1 ,...array2])]; // => remove duplication
Используя Set (ECMAScript 2015), это будет так просто:
const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = Array.from(new Set(array1.concat(array2)));
Вот немного другой взгляд на петлю. С некоторыми из оптимизаций в последней версии 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) на момент написания этой статьи.
Посмотрите ответ Майка и Дана Стокера, если вы хотите ускорить процесс. Это, безусловно, самый быстрый из всех результатов после прохождения почти всех жизнеспособных ответов.
Вы можете сделать это просто с помощью ECMAScript 6,
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
объединить два массива и удалить дубликат в 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 ]
ES6 решение для объединения
let arr1 = [1,2,3,4,5];
let arr2 = [3,4,5,6];
let result = [...new Set([...arr1, ...arr2])];
console.log(result);
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;
};
Значительно лучшая функция слияния массива.
Просто избегайте вложенных циклов (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);
}
Просто бросаю мои два цента.
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. Я честно понятия не имею, как браузер делает хэш, но он хорошо работает на многих тысячах точек данных.
Почему вы не используете объект? Похоже, вы пытаетесь смоделировать набор. Однако это не будет сохранять порядок.
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
}
Лучшее решение...
Вы можете проверить прямо в консоли браузера, нажав...
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"]
- Современный способ достижения этого - просто использовать оператор распространения.
- И чтобы избежать дублирования, мы можем эффективно использовать наборы; Наборы не допускают дублирования по умолчанию.
- Чтобы получить вывод как массив обратно из Set, мы можем использовать Array.from()
Итак, вот демонстрация для вашего сценария -
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);
Упрощенный simo answer и превратил его в приятную функцию.
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}
Мои полторы пенни:
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);
Вы можете достичь этого просто используя Underscore.js = > uniq:
array3 = _.uniq(array1.concat(array2))
console.log(array3)
Он напечатает [ "Vijendra", "Singh", "Shakya" ].
Новое решение (которое использует 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;
};
//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
Это можно сделать с помощью 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>
Для ES6 всего одна строка:
a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))] // [1, 2, 3, 4, 5]
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]
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, и это был бы единственный способ уважения к цепочке - определение новой функции нарушит ее, поэтому я думаю, что это как единственный способ добиться этого)
ради этого... вот однолинейное решение:
const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()
// ['A', 'B', 'C']
Не особенно читаемый, но он может помочь кому-то:
Set
.Set
в массив.sort()
применяется к новому массиву.Я написал эту простую функцию, которая принимает несколько аргументов массива. В значительной степени то же, что и решение выше, просто имеет более практичный вариант использования. Эта функция не объединяет повторяющиеся значения в один массив только для того, чтобы удалить их на более позднем этапе.
ОПРЕДЕЛЕНИЕ КОРОТКИХ ФУНКЦИЙ (всего 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]
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]
Самое простое решение с фильтром:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var mergedArrayWithoutDuplicates = array1.concat(
array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem))
);
В 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);
});
Обновление
См. рабочий код.