У меня есть два массива JavaScript:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
Я хочу, чтобы вывод был:
var array3 = ["Vijendra","Singh","Shakya"];
Выходной массив должен удалить повторные слова.
Как объединить два массива в JavaScript, чтобы я получал только уникальные элементы из каждого массива в том же порядке, в который они были вставлены в исходные массивы?
Просто объединить массивы (без удаления дубликатов)
Array.concat
:& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
console.log(array1.concat(array2));
& Лт;!- конец фрагмента - >
const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];
Поскольку нет «встроенного» способа удаления дубликатов (ECMA-262 на самом деле имеет «Array.forEach», что было бы здорово для этого), мы должны сделать это вручную:
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;
};
Затем использовать его:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique();
Это также сохранит порядок массивов (т. Е. Сортировка не требуется).
Поскольку многие люди раздражены расширением прототипа Array.prototype
и for in
, вот менее инвазивный способ его использования:
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));
Для тех, кому посчастливилось работать с браузерами, в которых доступен ES5, вы можете использовать Object.defineProperty
следующим образом:
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;
}
});
С Underscore.js или Lo-Dash вы можете сделать:
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
console.log(_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]));
& Лт;!- язык: lang-html - >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"> < / script >& Лт;!- конец фрагмента - >
Сначала объедините два массива, затем отфильтруйте только уникальные элементы:
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
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]
& Лт;!- конец фрагмента - >
Как было предложено, более разумным решением было бы отфильтровать уникальные элементы в b
перед объединением с a
:
& Лт;!- начать фрагмент: js hide: ложная консоль: истинная павиана: false - >
var a = [1, 2, 3], b = [101, 2, 1, 10]
var c = a.concat(b.filter((item) => a.indexOf(item) < 0))
console.log(c) // c is [1, 2, 3, 101, 10]
& Лт;!- конец фрагмента - >
Это решение ECMAScript & nbsp; 6 с использованием [оператора спред][1] и дженериков массива.
В настоящее время он работает только с Firefox и, возможно, с Internet & nbsp; 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))];
}
[1]: http://kangax.github.io/compat-table/es6/#spread_%28...% 29_operator
array1.push(...array2) // => don't remove duplication
[...array1,...array2] // => don't remove duplication
[...new Set([...array1 ,...array2])]; // => remove duplication
С помощью установка (в 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-rrays-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: ~ 589k ops / s < br / > фильтр: ~ 445k операций / с < br / > lodash: 308k операций / с < br / > для петель: 225 КБ опс / с
В комментарии указывалось, что одна из моих переменных настройки заставляла мой цикл опережать остальных, потому что ему не нужно было инициализировать пустой массив для записи. Я согласен с этим, поэтому я переписал тест даже на игровое поле и включил еще более быстрый вариант.
http://jsperf.com/merge-two-rrays-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) все еще значительно медленнее. Лодаш все еще сильна, и я все равно рекомендую его всем, кто не против добавить библиотеку в свой проект. Для тех, кто не хочет, мой цикл while по-прежнему является хорошим ответом, и ответ фильтра имеет очень сильный показ здесь, выбивая все мои тесты с последним Canary Chrome (44.0.2360) на момент написания этой статьи.
Проверьте ответ Майка и ответ Дэна Стокера, если вы хотите увеличить его на ступеньку выше. Это, безусловно, самый быстрый из всех результатов после прохождения почти всех жизнеспособных ответов.
Вы можете сделать это просто с ECMAScript & nbsp; 6,
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
Решение, основанное на ES6 Союза
в
let arr1 = [1,2,3,4,5];
let arr2 = [3,4,5,6];
let result = [...new Set([...arr1, ...arr2])];
console.log(result);
в
объединить два массива и удалить дубликат в 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 ]
Просто держитесь подальше от вложенных циклов (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);
}
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;
};
Гораздо лучшая функция слияния массива.
Просто бросаю мои два цента.
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;
}
Этот метод я часто использую, он использует объект в качестве таблицы хеш-смотров для проверки дубликатов. Предполагая, что хеш - O (1), он запускается в O (n), где n - a.length + 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
}
- современный способ добиться этого-просто использовать распространение оператора.
- И, чтобы избежать дублирования, мы можем эффективно использовать наборы; наборы выиграл'т разрешить дубликаты по умолчанию.
- Для получения выходных данных в виде массива из набора, можно использовать массив.из()
Итак, здесь'с демонстрацией для вашего сценария
в
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);
в
Лучшее решение...
Вы можете проверить прямо в консоли браузера, нажав...
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"]
Упрощен ответ Симо и превратил его в хорошую функцию.
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's = > uniq :
array3 = _.uniq(array1.concat(array2))
console.log(array3)
Он напечатает ["Виджендра", "Сингх", "Шакья"] .
Новое решение (в котором используются 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;
};