2つのJavaScript配列があります。
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
出力を次のようにします。
var array3 = ["Vijendra","Singh","Shakya"];
出力配列から繰り返し単語を削除する必要があります。
2つの配列をJavaScriptでマージして、元の配列に挿入されたのと同じ順序で各配列から一意の項目のみを取得する方法を教えてください。
(重複を削除せずに)配列をマージするだけ
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];
重複を削除するための「組み込み」の方法はありません( 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を使えば、次のことができます。
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2, 3, 101, 10]
まず2つの配列を連結し、次に固有の項目だけを除外します。
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/
@Dmitry(下記の2番目のコメントを参照)によって示唆されているように、よりパフォーマンス的な解決策はb
と連結する前に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]
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での最適化によっては、2つの配列の和集合を解決するための最速の方法です(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ループ:〜589k ops/s
フィルター:〜445k ops/s
lodash:308k ops/s
ループ用:225k ops/s
コメントは、私の設定変数の1つが、書き込みのために空の配列を初期化する必要がないため、ループが他のループよりも先に進むことを引き起こしていることを指摘しました。私はそれに同意するので、私は競技場にもテストを書き換えて、さらに速いオプションを含めました。
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;
};
この代替ソリューションでは、1つの回答の連想配列ソリューションを組み合わせてループ内の.indexOf()
呼び出しを排除しました。2つ目のループで処理が大幅に遅くなり、他のユーザーが回答として提案したその他の最適化も含まれます。そうですね。
すべての値(i-1)に対する二重ループを使用したここでの一番の答えは、まだかなり遅いです。 lodashはまだ力強い活動をしています、そして私はまだ彼らのプロジェクトにライブラリを追加することを気にしない人にはそれをお勧めします。したくない人のために、私のwhileループはまだ良い答えであり、フィルターの答えはここで非常に強い結果を示しており、この記事を書いている時点で最新のCanary Chrome(44.0.2360)ですべてを打ち負かしました。
マイクの答え および ダン・ストッカーの答え スピードを一段階上げたい場合は/をチェックしてください。ほとんどすべての実行可能な答えを調べた後、これらははるかにすべての結果の中で最速です。
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;
};
はるかに優れた配列マージ機能
2つの配列をマージし、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);
}
私の2セントを投げ込むだけです。
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
}
私の一人半ペニー:
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);
最善の解決策.
あなたが押すことによってブラウザコンソールで直接チェックすることができます...
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])
あなたが重複しないで欲しいならば、あなたはここからより良い解決策を試すことができます - Shouting Code 。
[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"]
単純化された simoの答え そしてそれをNice関数に変えました。
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}
Underscore.jsの=> uniq を使って簡単に実現できます。
array3 = _.uniq(array1.concat(array2))
console.log(array3)
["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
}
他のブラウザ用の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>
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)
これに関して良いことはパフォーマンスです、そして一般的に、あなたがその配列を扱うとき、filter、mapなどのような方法を連鎖しているので、あなたはその行を加えることができます。 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を汚染するのは好きではないし、それがチェーンを尊重する唯一の方法になるだろう - 新しい関数を定義することはそれを壊すだろう - だから私はこれを達成する唯一の方法がこのようなものだと思う
新しい解決策(これは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(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;
};
ES6の場合は、1行だけです。
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]
それのために...これは単一行の解決策です:
const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()
// ['A', 'B', 'C']
特に読みやすくはありませんが、誰かに役立つ可能性があります。
Set
を作成するためのコンストラクタパラメータとして渡されます。Set
を配列に変換するために使用されます。sort()
関数は新しい配列に適用されます。機能的なアプローチに従うと、2つのunion
name__sのArray
name__は、単にconcat
name__とfilter
name__の合成です。最適なパフォーマンスを提供するために、プロパティ検索に最適化されたネイティブのSet
name__データ型を使用します。
とにかく、union
name__関数と関連した重要な質問は、どのように重複を扱うかです。以下の並べ替えが可能です。
Array A + Array B
[unique] + [unique]
[duplicated] + [unique]
[unique] + [duplicated]
[duplicated] + [duplicated]
最初の2つの置換は、単一の関数で簡単に処理できます。ただし、最後の2つは、Set
name__検索に依存している限り処理できないため、より複雑です。普通の古いObject
name__プロパティ検索への切り替えは深刻なパフォーマンスヒットを伴うことになるので、以下の実装では3番目と4番目の置換を無視しています。あなたはそれらをサポートするためにunion
name__の別のバージョンを構築しなければならないでしょう。
// 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) );
これ以降は、任意の数の配列を受け入れるunionn
name__関数を実装するのは簡単です(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) );
unionn
name__は単なるfoldl
name__(別名Array.prototype.reduce
)です。これはunion
name__をそのリデューサーとして取ります。注:実装は追加のアキュムレータを使用しないため、引数なしで適用するとエラーをスローします。
これを行う最も簡単な方法は、concat()
を使用して配列をマージしてからfilter()
を使用して重複を削除するか、concat()
を使用してからマージした配列をSet()
の中に入れることです。
最初の方法:
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]
2番目の方法(ただし、UIにパフォーマンスの影響がある)
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);
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);
});
更新
実用的なコードを見てください。
元の配列が重複排除を必要としないと仮定すると、これはかなり速く、元の順序を保持し、元の配列を変更しないはずです。
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;
}
使用法:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = arrayMerge(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);
無制限の数の配列または非配列をマージして一意にします。
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]
受け入れられた答えは私のテストでは最も遅いようです。
note - Key によって2つのオブジェクトの配列をマージします
<!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>
Filterを使った最も簡単な解決策:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var mergedArrayWithoutDuplicates = array1.concat(
array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem))
);
私は複数の配列引数をとるこの単純な関数を書きました。この関数は、重複した値を1つの配列にのみ連結して、後でそれらを削除できるようにすることはしません。
ショートファンクション定義(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);
}
使用例 _ 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]
あなたのレビューのためのreduce funcによるもう一つのアプローチ:
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"];
これは簡単で、jQueryを使って1行で実行できます。
var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya'];
$.unique(arr1.concat(arr2))//one line
["Vijendra", "Singh", "Shakya"]
LiraNunaのセグエとしての1行ソリューション
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);
これは簡単な例です:
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"]));
冗長な要素を削除するためにunique(array)
を定義し、2つの配列を組み合わせるためにconcat
関数を使います。
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 });
}
辞書とJqueryを利用すると、2つの配列をマージして重複を避けることができます。私の例では、オブジェクトに与えられたフィールドを使っていますが、オブジェクトそのものでも構いません。
Lodashを使う
@ GijsjanBの答えは便利だと思いましたが、私の配列には多くの属性を持つオブジェクトが含まれていたので、属性の1つを使ってそれらを重複排除する必要がありました。
これが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 }]
3番目のパラメータとして渡す関数には2つの引数(2つの要素)があり、それらが等しい場合はtrue
を返す必要があります。
2つの配列をスプレッド演算子で連結する生意気な小さな方法を学びました:
var array1 = ['tom', 'dick', 'harry'];
var array2 = ['martin', 'ricky'];
array1.Push(...array2);
"..."スプレッド演算子は次の配列を個々の項目に分割し、それからPushはそれらを別々の引数として扱うことができます。
これは私の2番目の答えですが、私は最速だと思いますか?誰かに私のことを確認してもらい、コメントに答えてほしいのですが。
私の最初の試みは約99k ops/secを打った、そしてこれが回避するのは390k ops/sec対140kの他の主要なjsperfテストを言っている。
http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26
今回はできるだけアレイの相互作用をできるだけ少なくするようにしましたが、パフォーマンスが向上したように見えました。
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;
}
編集:私は私の機能にいくつかの変更を加えました、そしてパフォーマンスはjsperfサイトの他のものと比較して劇的です。
特定のプロパティ(IDなど)の重複が不要な場合
let noDuplicate = array1.filter ( i => array2.findIndex(a => i.id==a.id)==-1 );
let result = [...noDuplicate, ...array2];
一意のオブジェクトをチェックしたい場合は、比較にJSON.stringifyを使用してください。
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;
}
計算時間の観点から、これが最も効果的なものです。また、それは要素の初期の順序を保ちます。
最初に2番目の配列からすべての重複をフィルター処理し、次に最初の配列に残っているものを連結します。
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]
これは、配列が値を見逃してはいけないという欠点を伴い、少し改良された(より速い)バージョンです。
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));
- これを実現する最新の方法は、単純に拡散演算子を使用することです。
- また、重複を避けるために、Setsを効率的に使用できます。 集合はデフォルトで複製を許可しません。
- Setから配列として出力を取得するには、Array.from()を使用します。
だから、これはあなたのシナリオのためのデモンストレーションです -
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var resArr = Array.from(new Set([...array1, ...array2]));
console.log(resArr);
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())];
}
flat()
関数のためにES2019ですが、 core-js を使用してポリフィルとして取得できます。ここのT
はTypeScriptジェネリック型であり、TypeScriptを使用していない場合は削除できます。 TypeScriptを使用している場合は、"lib": ["es2019.array"]
のコンパイラオプションにtsconfig.json
を追加してください。
lodashを使用するだけ _。union
これは、2つの重要な機能を組み合わせることによって達成できます。
const getUniqueMerge = (...arrs) => getUniqueArr(mergeArrs(...arrs))
const getUniqueArr = (array) => Array.from(new Set(array))
const mergeArrs = (...arrs) => [].concat(...arrs)
無制限の配列や値を扱うことができます
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"]
私はこれがより速く働くと思います。
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;
}
私のように、あなたがより古いブラウザをサポートする必要があるならば、これは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
これが私の解決策であり、{ https://Gist.github.com/4692150 } _であり、結果が等しく、使いやすい結果です。
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"]
]
これを試すことができます:
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]);
};
試してください:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
array1.pushUnique(array2);
alert(array1.toString()); // Output: Vijendra,Singh,Shakya
使用法: 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;
}
あなたが純粋にunderscore.jsを使っているのであれば、それはunionWith、unionByを持っていません。
試してみることができます: _.uniq(_.union(arr1, arr2), (obj) => obj.key)
(keyは各オブジェクトのキー・パラメーターです)これは、両方の配列の結合後に一意になるのに役立ちます。
同じ理由で前に書いただけです(どんな量の配列でも動作します)。
/**
* 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; }
そのための最も簡単で簡単な方法は、配列にオブジェクトの要素が含まれているかどうかを示すtrueまたはfalseを返すJavaScriptの関数 "some()"を使用することです。あなたはこれを作ることができます:
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);
結果:
["Vijendra", "Singh", "Shakya"]
あなたが望むss ...それを複製せずに...