私は、一意であることを確認するために必要な数の配列を持っています。私はインターネット上で以下のコードスニペットを見つけました、そしてそれは配列がそれにゼロを持つまでうまく働きます。私は この他のスクリプト こちらSOを見ましたが、ほぼ正確に見えますが、失敗することはありません。
それで、私が学ぶのを手助けするために、誰かが私がプロトタイプスクリプトがどこでうまくいかないのかを決めるのを手伝うことができますか?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.Push (e)};
return a;
}
JavaScript 1.6 // ECMAScript 5 を使用すると、次のようにネイティブの filter
メソッドを使用して一意の値を持つ配列を取得できます。
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage example:
var a = ['a', 1, 'a', 2, '1'];
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
ネイティブメソッドfilter
は配列をループして、与えられたコールバック関数onlyUnique
を渡すエントリだけを残します。
onlyUnique
は与えられた値が最初に現れるものであるかどうかを調べます。そうでなければ、それは複製でなければならず、コピーされません。
このソリューションは、jQueryやprototype.jsのような追加のライブラリがなくても機能します。
値が混在する配列に対しても機能します。
ネイティブメソッドfilter
とindexOf
をサポートしていない古いブラウザ(<ie9)では、 filter と indexOf のMDNドキュメントに回避策があります。
最後に出現した値を保持したい場合は、単純にindexOf
をlastIndexOf
に置き換えます。
ES6では、これを短くすることができます。
// usage example:
var myArray = ['a', 1, 'a', 2, '1'];
var unique = myArray.filter((v, i, a) => a.indexOf(v) === i);
// unique is ['a', 1, 2, '1']
Camilo Martin にコメントのヒントをありがとう。
ES6には、固有の値を格納するためのネイティブオブジェクト Set
があります。一意の値を持つ配列を取得するには、これを実行します。
var myArray = ['a', 1, 'a', 2, '1'];
let unique = [...new Set(myArray)];
// unique is ['a', 1, 2, '1']
Set
のコンストラクタはArrayのような反復可能なオブジェクトを取り、拡散演算子...
はセットをArrayに変換します。 Lukas Liese にコメントのヒントをありがとう。
underscore.js を使用することもできます。
console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>
これが返されます:
[1, 2, 3, 4]
この質問にはすでに30以上の答えがあることを私は理解しています。しかし、私は最初に既存のすべての答えを読み、私自身の研究をしました。
すべての答えを4つの可能な解決策に分けました。
[...new Set( [1, 1, 2] )];
{ }
を使う[ ]
を使うfilter + indexOf
を使うこれが回答に含まれているサンプルコードです。
[...new Set( [1, 1, 2] )];
function uniqueArray0(array) {
var result = Array.from(new Set(array));
return result
}
{ }
を使うfunction uniqueArray1( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
[ ]
を使うfunction uniqueArray2(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.Push(arr[i]);
return a;
}
filter + indexOf
を使うfunction uniqueArray3(a) {
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
// usage
var unique = a.filter( onlyUnique ); // returns ['a', 1, 2, '1']
return unique;
}
そしてどちらが速いのか疑問に思いました。テスト用に サンプルのGoogleシート を作成しました。注:ECMA 6はGoogleスプレッドシートでは入手できないため、テストできません。
ハッシュを使っているので、オブジェクト{ }
を使っているコードが勝つことを期待していました。そのため、ChromeとIEでテストがこのアルゴリズムに対して最良の結果を示したことをうれしく思います。 コード の@rabに感謝します。
私はそれ以来jQueryを使うNiceメソッドを見つけました
arr = $.grep(arr, function(v, k){
return $.inArray(v ,arr) === k;
});
注:このコードは、 Paul Irishのアヒルのパンチポストから引っ張られた - 私は信用を与えるのを忘れていた:
ES6による最短の解決策:[...new Set( [1, 1, 2] )];
あるいは、元の質問のように、Arrayプロトタイプを変更したい場合は、
Array.prototype.getUnique = function() {
return [...new Set( [this] )];
};
EcmaScript 6は、現時点(2015年8月)で 部分的に実装された のみですが、 Babel はES6(およびES7まで)をES5に変換するのに非常に普及しています。そうすれば、今日ES6コードを書くことができます。
...
の意味がわからない場合は、 スプレッド演算子 と呼ばれます。 From _ mdn _ :«スプレッド演算子を使うと、複数の引数(関数呼び出しの場合)または複数の要素(配列リテラルの場合)が必要な場所で式を展開できます。 Setはイテラブルなので(そしてユニークな値しか持てません)、spread演算子はSetを展開して配列を埋めます。
ES6を学ぶためのリソース:
最も簡単な解決策:
var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log([...new Set(arr)]);
または
var arr = [1, 3, 4, 1, 2, 1, 3, 3, 4, 1];
console.log(Array.from(new Set(arr)));
これを行うための最も簡単で、かつ 最速 (Chrome)の方法:
Array.prototype.unique = function() {
var a = [];
for (var i=0, l=this.length; i<l; i++)
if (a.indexOf(this[i]) === -1)
a.Push(this[i]);
return a;
}
単に配列内のすべての項目を調べて、その項目がすでにリストに含まれているかどうかをテストします。含まれていない場合は、返される配列にプッシュします。
JsPerfによると、この関数は 私がどこにでも見つけることができるものの中で最も速い - あなた自身のものを追加しても構いません。
非プロトタイプ版
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
if (a.indexOf(arr[i]) === -1 && arr[i] !== '')
a.Push(arr[i]);
return a;
}
配列をソートする必要があるときは、次のものが最速です。
Array.prototype.sortUnique = function() {
this.sort();
var last_i;
for (var i=0;i<this.length;i++)
if ((last_i = this.lastIndexOf(this[i])) !== i)
this.splice(i+1, last_i-i);
return this;
}
または非プロトタイプ
function sortUnique(arr) {
arr.sort();
var last_i;
for (var i=0;i<arr.length;i++)
if ((last_i = arr.lastIndexOf(arr[i])) !== i)
arr.splice(i+1, last_i-i);
return arr;
}
これはまた 上記の方法よりも速い ほとんどの非クロム製ブラウザで。
パフォーマンスのみ!このコードは、おそらくここにあるすべてのコードよりも10倍高速です*すべてのブラウザで動作し、メモリへの影響も最小です。
古い配列を再利用する必要がない場合は、ここで一意に変換する前に必要な他の操作を実行するのがおそらくこれを行う最も速い方法であり、非常に短いです。
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
その後、これを試すことができます
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];
function toUnique(a, b, c) { //array,placeholder,placeholder
b = a.length;
while (c = --b)
while (c--) a[b] !== a[c] || a.splice(c, 1);
return a // not needed ;)
}
console.log(toUnique(array));
//[3, 4, 5, 6, 7, 8, 9, 0, 2, 1]
この記事を読んでこの関数を思いついた...
http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
私はforループが好きではありません。 while--ループのような多くのparameters.iが必要です。一方、私たち全員が好きなものを除くすべてのブラウザで最も速いループです...クロム。
とにかく、whileを使用する最初の関数を作成しました。そして、記事で見つかった関数よりも少し高速ですが、十分ではありません。unique2()
次のステップでは、モダンなjs .Object.keys
を使用します。もう一方のforループをjs1.7のObject.keysに置き換えます...少し速くて短くなりました(chromeで2倍高速);)。十分ではありません!.unique3()
。
この時点で、私の独自の機能に本当に必要なものを考えていました。古い配列は必要ありません。高速な機能が必要です。したがって、2つのwhileループ+ spliceを使用しました。unique4()
言うまでもなく、私は感銘を受けました。
chrome:通常の1秒あたり150,000操作は、1秒あたり1,800,000操作にジャンプしました。
ie:80,000 op/s vs 3,500,000 op/s
ios:18,000 op/s対170,000 op/s
safari:80,000 op/s vs 6,000,000 op/s
Proofhttp://jsperf.com/wg または、console.time ... microtime ...何でも使用
unique5()
は、古い配列を保持したい場合に何が起こるかを示すためのものです。
あなたが何をしているかわからない場合は、Array.prototype
を使用しないでください。私はたくさんのコピーと過去をしました。ネイティブなprototype.exampleを作成する場合は、Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})
を使用します。 https://stackoverflow.com/a/20463021/24507
注:古い配列は、この操作の後に破棄/一意になります。
上記のコードを読むことができない場合は、JavaScriptの本を読むか、短いコードについて説明します。 https://stackoverflow.com/a/21353032/24507
一部はindexOf
を使用しています...しないでください... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh
空の配列の場合
!array.length||toUnique(array);
ここでの答えの多くは初心者には役に立たないかもしれません。配列を重複排除するのが難しい場合は、プロトタイプチェーン、あるいはjQueryについて実際に知っているでしょうか。
最近のブラウザでは、明確で単純な解決策は Set にデータを格納することです。これは一意の値のリストになるように設計されています。
const cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
const uniqueCars = Array.from(new Set(cars));
Array.from
はSetをArrayに変換し直すのに便利です。そうすれば、その配列が持っているすべての素晴らしいメソッド(機能)に簡単にアクセスできます。同じことをする 他の方法もあります 。 Setには forEach のような便利な機能がたくさんあるので、Array.from
はまったく必要ないかもしれません。
古いInternet Explorerをサポートする必要があるためにSetを使用できない場合、簡単な方法は、アイテムが新しい配列に含まれているかどうかを事前に確認しながら、新しい配列にコピーすることです。
// Create a list of cars, with duplicates.
var cars = ['Volvo', 'Jeep', 'Volvo', 'Lincoln', 'Lincoln', 'Ford'];
// Create a list of unique cars, to put a car in if we haven't already.
var uniqueCars = [];
// Go through each car, one at a time.
cars.forEach(function (car) {
// The code within the following block runs only if the
// current car does NOT exist in the uniqueCars list
// - a.k.a. prevent duplicates
if (uniqueCars.indexOf(car) === -1) {
// Since we now know we haven't seen this car before,
// copy it to the end of the uniqueCars list.
uniqueCars.Push(car);
}
});
これを即座に再利用可能にするために、それを関数に入れましょう。
function deduplicate(data) {
if (data.length > 0) {
var result = [];
data.forEach(function (elem) {
if (result.indexOf(elem) === -1) {
result.Push(elem);
}
});
return result;
}
}
それで、重複を取り除くために、これを行います。
var uniqueCars = deduplicate(cars);
deduplicate(cars)
の部分 は になり、関数が完了するとresultという名前になります。
好きな配列の名前を渡すだけです。
["Defects", "Total", "Days", "City", "Defects"].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
[0,1,2,0,3,2,1,5].reduce(function(prev, cur) {
return (prev.indexOf(cur) < 0) ? prev.concat([cur]) : prev;
}, []);
このプロトタイプgetUnique
は完全に正しくありません。なぜなら、もし私が["1",1,2,3,4,1,"foo"]
のような配列を持っていれば["1","2","3","4"]
を返し、"1"
は文字列で1
は整数だからです。それらは違う。
これが正しい解決策です。
Array.prototype.unique = function(a){
return function(){ return this.filter(a) }
}(function(a,b,c){ return c.indexOf(a,b+1) < 0 });
を使用して:
var foo;
foo = ["1",1,2,3,4,1,"foo"];
foo.unique();
上記は["1",2,3,4,1,"foo"]
を生成します。
ES6セットを使ってこれを行うことができます。
var duplicatedArray = [1,2,3,4,5,1,1,1,2,3,4];
var uniqueArray = Array.from(new Set(duplicatedArray));
//出力は
uniqueArray = [1,2,3,4,5];
Array.prototypeを拡張すること(これは悪い習慣であると言われています)やjquery/underscoreを使わずに、単に配列をfilter
することができます。
最後の出現を保つことによって:
function arrayLastUnique(array) {
return array.filter(function (a, b, c) {
// keeps last occurrence
return c.indexOf(a, b + 1) < 0;
});
},
または最初の出現
function arrayFirstUnique(array) {
return array.filter(function (a, b, c) {
// keeps first occurrence
return c.indexOf(a) === b;
});
},
えーと、それはJavaScript ECMAScript 5以降、つまりIE 9以降のみを意味しますが、ネイティブHTML/JS(Windowsストアアプリ、Firefox OS、Sencha、PhoneGap、Titaniumなど)での開発には最適です。
これは、0
がJavaScriptでは誤った値であるためです。
配列の値が0またはその他の偽の値の場合、this[i]
は偽になります。
プロトタイプフレームワークを使用している場合は、「for」ループを実行する必要はありません。 http://www.prototypejs.org/api/array/uniq を次のように使用できます。
var a = Array.uniq();
これにより、重複のない重複配列が生成されます。私はあなたの質問に遭遇しました。
uniq()
私が使った
サイズ()
そして私の簡単な結果がありました。 p.s入力ミスして申し訳ありません。
編集:あなたが未定義のレコードをエスケープしたい場合は追加することができます
コンパクト()
前に、このように:
var a = Array.compact().uniq();
Array.prototype.getUnique = function() {
var o = {}, a = []
for (var i = 0; i < this.length; i++) o[this[i]] = 1
for (var e in o) a.Push(e)
return a
}
奇妙なことに、これまでには示唆されていませんでした..配列内のオブジェクトキー(以下のid
)で重複を削除するには、次のようにします。
const uniqArray = array.filter((obj, idx, arr) => (
arr.findIndex((o) => o.id === obj.id) === idx
))
Gabriel Silveiraがこのように関数を作成した理由はよくわかりませんが、単純化された形式でも最小化なしで同様に機能する単純な形式は、
Array.prototype.unique = function() {
return this.filter(function(value, index, array) {
return array.indexOf(value, index + 1) < 0;
});
};
またはCoffeeScriptでは:
Array.prototype.unique = ->
this.filter( (value, index, array) ->
array.indexOf(value, index + 1) < 0
)
簡単な方法で一意の配列値を見つける
function arrUnique(a){
var t = [];
for(var x = 0; x < a.length; x++){
if(t.indexOf(a[x]) == -1)t.Push(a[x]);
}
return t;
}
arrUnique([1,4,2,7,1,5,9,2,4,7,2]) // [1, 4, 2, 7, 5, 9]
Shamasis Bhattacharya のブログから (O(2n)time複雑さ)
Array.prototype.unique = function() {
var o = {}, i, l = this.length, r = [];
for(i=0; i<l;i+=1) o[this[i]] = this[i];
for(i in o) r.Push(o[i]);
return r;
};
Paul Irish のブログから :JQueryの改善 .unique()
:
(function($){
var _old = $.unique;
$.unique = function(arr){
// do the default behavior only if we got an array of elements
if (!!arr[0].nodeType){
return _old.apply(this,arguments);
} else {
// reduce the array to contain no dupes via grep/inArray
return $.grep(arr,function(v,k){
return $.inArray(v,arr) === k;
});
}
};
})(jQuery);
// in use..
var arr = ['first',7,true,2,7,true,'last','last'];
$.unique(arr); // ["first", 7, true, 2, "last"]
var arr = [1,2,3,4,5,4,3,2,1];
$.unique(arr); // [1, 2, 3, 4, 5]
逆の問題を解決するには、配列をロードするときに重複しないようにすると便利です。 Set オブジェクトでも同様ですが、すべてのブラウザで使用できるわけではありません。それはメモリを節約し、あなたがその内容を何度も見る必要があるならより効率的です。
Array.prototype.add = function (elem) {
if (this.indexOf(elem) == -1) {
this.Push(elem);
}
}
サンプル:
set = [];
[1,3,4,1,2,1,3,3,4,1].forEach(function(x) { set.add(x); });
set = [1,3,4,2]
を渡します
a.filter(( t={}, e=>!(t[e]=e in t) ))
O(n) パフォーマンス ;あなたの配列はa
にあると仮定します。説明 ここ (+ Jeppe 改善)
var a1 = [5,6,0,4,9,2,3,5,0,3,4,1,5,4,9];
var a2 = [[2, 17], [2, 17], [2, 17], [1, 12], [5, 9], [1, 12], [6, 2], [1, 12]];
var a3 = ['Mike', 'Adam','Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl'];
let nd = (a) => a.filter((t={},e=>!(t[e]=e in t)))
// print
let c= x => console.log(JSON.stringify(x));
c( nd(a1) );
c( nd(a2) );
c( nd(a3) );
ハッシュキーをシリアル化すると、これがオブジェクトに対して機能するようになるのに役立ちます。
Array.prototype.getUnique = function() {
var hash = {}, result = [], key;
for ( var i = 0, l = this.length; i < l; ++i ) {
key = JSON.stringify(this[i]);
if ( !hash.hasOwnProperty(key) ) {
hash[key] = true;
result.Push(this[i]);
}
}
return result;
}
追加の依存関係があっても問題ない場合、またはコードベースにすでにライブラリの1つがある場合は、LoDash(またはUnderscore)を使用して、配列から重複したものを削除できます。
使用法
まだコードベースに持っていない場合は、npmを使ってインストールします。
npm install lodash
その後、次のように使用してください。
import _ from 'lodash';
let idArray = _.uniq ([
1,
2,
3,
3,
3
]);
console.dir(idArray);
でる:
[ 1, 2, 3 ]
[1,2,2,3,1].unique() // => [1,2,3]
[{id:5, name:"Jay"}, {id:6, name:"Jay"}, {id: 5, name:"Jay"}].unique('id')
// => [{id:5, name:"Jay"}, {id:6, name:"Jay"}]
var arr = [2,3,4,2,3,4,2];
const result = [...new Set(arr)];
console.log(result);
これを見てください。 Jqueryは独自のメソッドを提供します。 https://api.jquery.com/jQuery.unique/
var ids_array = []
$.each($(my_elements), function(index, el) {
var id = $(this).attr("id")
ids_array.Push(id)
});
var clean_ids_array = jQuery.unique(ids_array)
$.each(clean_ids_array, function(index, id) {
elment = $("#" + id) // my uniq element
// TODO WITH MY ELEMENT
});
オブジェクトキーを使ってユニークな配列を作るために、私は以下を試してみました
function uniqueArray( ar ) {
var j = {};
ar.forEach( function(v) {
j[v+ '::' + typeof v] = v;
});
return Object.keys(j).map(function(v){
return j[v];
});
}
uniqueArray(["1",1,2,3,4,1,"foo", false, false, null,1]);
これは["1", 1, 2, 3, 4, "foo", false, null]
を返します
これが配列からユニークなアイテムを取得する最も簡単な方法だと思います。
var arr = [1,2,4,1,4];
arr = Array.from(new Set(arr))
console.log(arr)
強力な reduce メソッド( ≥5.1 )を利用できる場合は、次のようにして試すことができます。
Array.prototype.uniq = function() {
return this.reduce(function(sofar, cur) {
return sofar.indexOf(cur) < 0 ? sofar.concat([cur]) : sofar;
}, []);
};
これは最も効率的な実装ではありません(indexOf
チェックのため、最悪の場合はリスト全体を調べます)。効率が重要な場合は、発生の「履歴」を何らかのランダムアクセス構造(たとえば{}
)に保持し、代わりにそれらをキー入力できます。それが基本的に 最も投票された答え がすることなので、例としてそれをチェックしてください。
[...new Set(duplicates)]
これは最も単純なものであり、MDN Web Docsから参照されます。
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)]) // [2, 3, 4, 5, 6, 7, 32]
これはうまくいくでしょう。
function getUnique(a) {
var b = [a[0]], i, j, tmp;
for (i = 1; i < a.length; i++) {
tmp = 1;
for (j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
tmp = 0;
break;
}
}
if (tmp) {
b.Push(a[i]);
}
}
return b;
}
lodash およびidentity lambda関数で実行してください。オブジェクトを使用する前に定義してください
const _ = require('lodash');
...
_.uniqBy([{a:1,b:2},{a:1,b:2},{a:1,b:3}], v=>v.a.toString()+v.b.toString())
_.uniq([1,2,3,3,'a','a','x'])
そして持っているでしょう:
[{a:1,b:2},{a:1,b:3}]
[1,2,3,'a','x']
(これが最も簡単な方法です)
他の答えを基にして、戦略を選択するためにオプションのフラグを取る別の変種があります(最初に出現するか最後に保つ):
拡張なし Array.prototype
function unique(arr, keepLast) {
return arr.filter(function (value, index, array) {
return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
});
};
// Usage
unique(['a', 1, 2, '1', 1, 3, 2, 6]); // -> ['a', 1, 2, '1', 3, 6]
unique(['a', 1, 2, '1', 1, 3, 2, 6], true); // -> ['a', '1', 1, 3, 2, 6]
拡張 Array.prototype
Array.prototype.unique = function (keepLast) {
return this.filter(function (value, index, array) {
return keepLast ? array.indexOf(value, index + 1) < 0 : array.indexOf(value) === index;
});
};
// Usage
['a', 1, 2, '1', 1, 3, 2, 6].unique(); // -> ['a', 1, 2, '1', 3, 6]
['a', 1, 2, '1', 1, 3, 2, 6].unique(true); // -> ['a', '1', 1, 3, 2, 6]
JQueryも使えます
var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];
// note: jQuery's filter params are opposite of javascript's native implementation :(
var unique = $.makeArray($(a).filter(function(i,itm){
// note: 'index', not 'indexOf'
return i == $(a).index(itm);
}));
// unique: [1, 5, 6, 4, 2, 3]
もともと答えた: 配列からすべての一意の要素を取得するためのjQuery関数?
重複排除では、通常、指定されたタイプの等価演算子が必要です。ただし、eq
関数を使用すると、Set
を===
にフォールバックするため、Set
を使用して効率的に重複を判断することができなくなります。ご存じのとおり、===
は参照型では機能しません。立ち往生しても親切ですよね?
解決策は、(参照)型をSet
を使用して実際にルックアップできるものに変換できる変換関数を使用することです。たとえば、ハッシュ関数を使用できます。関数が含まれていない場合は、JSON.stringify
データ構造を使用できます。
多くの場合、プロパティにアクセスするだけで、Object
の参照の代わりに比較できます。
これらの要件を満たす2つのコンビネーターを次に示します。
const dedupeOn = k => xs => {
const s = new Set();
return xs.filter(o =>
s.has(o[k])
? null
: (s.add(o[k]), o[k]));
};
const dedupeBy = f => xs => {
const s = new Set();
return xs.filter(x => {
const r = f(x);
return s.has(r)
? null
: (s.add(r), x);
});
};
const xs = [{foo: "a"}, {foo: "b"}, {foo: "A"}, {foo: "b"}, {foo: "c"}];
console.log(
dedupeOn("foo") (xs)); // [{foo: "a"}, {foo: "b"}, {foo: "A"}, {foo: "c"}]
console.log(
dedupeBy(o => o.foo.toLowerCase()) (xs)); // [{foo: "a"}, {foo: "b"}, {foo: "c"}]
これらのコンビネータにより、あらゆる種類の重複排除の問題に非常に柔軟に対応できます。それは断食法ではなく、最も表現力があり、最も一般的なものです。
私は配列から重複したidプロパティを持つオブジェクトを削除する必要があるところで私はわずかに異なる問題を抱えていた。これはうまくいった。
let objArr = [ { id: '123' }, { id: '123' }, { id: '456' } ];
objArr = objArr.reduce( ( acc, cur ) => [
...acc.filter( ( obj ) => obj.id !== cur.id ), cur
], [] );
私はes6 reduceを使用して重複を削除するための配列ヘルパーメソッドを見つけるという解決策を持っています。
let numbers = [2,2,3,3,5,6,6];
const removeDups = array => {
return array.reduce((acc, inc) => {
if(!acc.find( i => i === inc)) {
acc.Push(inc);
}
return acc;
},[]);
}
removeDups(numbers); /// [2,3,5,6]
Array.prototype.unique = function() {
var a = [],k = 0,e;
for(k=0;e=this[k];k++)
if(a.indexOf(e)==-1)
a.Push(e);
return a;
}
[1,2,3,4,33,23,2,3,22,1].unique(); // return [1,2,3,4,33,23,22]
私はこれがすでに死に答えられていることを知っています...しかし... linqのjavascriptの実装については誰も言及していません。そして.distinct()
メソッドを使うことができますコードを非常に読みやすくします。
var Linq = require('linq-es2015');
var distinctValues = Linq.asEnumerable(testValues)
.Select(x)
.distinct()
.toArray();
var testValues = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 1];
var distinctValues = Enumerable.asEnumerable(testValues)
.distinct()
.toArray();
console.log(distinctValues);
<script src="https://npmcdn.com/linq-es5/dist/linq.js"></script>
Idとしてfield [2]を使って、ユニークな配列の配列を作る:
[ [ '497', 'Q0', 'WTX091-B06-138', '0', '1.000000000', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B09-92', '1', '0.866899288', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B09-92', '2', '0.846036819', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B09-57', '3', '0.835025326', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B43-79', '4', '0.765068215', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B43-56', '5', '0.764211464', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B44-448', '6', '0.761701704', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B44-12', '7', '0.761701704', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B49-128', '8', '0.747434800', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B18-17', '9', '0.746724770', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B19-374', '10', '0.733379549', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B19-344', '11', '0.731421782', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B09-92', '12', '0.726450470', 'GROUP001' ],
[ '497', 'Q0', 'WTX091-B19-174', '13', '0.712757036', 'GROUP001' ] ]
.filter((val1, idx1, arr) => !!~val1.indexOf(val1[2]) &&
!(arr.filter((val2, idx2) => !!~val2.indexOf(val1[2]) &&
idx2 < idx1).length));
これは純粋ではない、それは配列を変更しますが、これは最速のものです。あなたの方が速いなら、それからコメントを書いてください;)
http://jsperf.com/unique-array-webdeb
Array.prototype.uniq = function(){
for(var i = 0, l = this.length; i < l; ++i){
var item = this[i];
var duplicateIdx = this.indexOf(item, i + 1);
while(duplicateIdx != -1) {
this.splice(duplicateIdx, 1);
duplicateIdx = this.indexOf(item, duplicateIdx);
l--;
}
}
return this;
}
[
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc",
"",2,4,"A","abc"
].uniq() // ["",2,4,"A","abc"]
var numbers = [1,1,2,3,4,4];
function unique(dupArray) {
return dupArray.reduce(function (previous, num){
if (previous.find(function(item){
return item == num;
})) {
return previous;
} else {
previous.Push(num);
return previous;
}
}, [])
}
var check = unique(numbers);
console.log(check);
山のためのさらに別の解決策。
私は最近ソートされたリストをユニークにする必要があり、私はこのようなオブジェクトの前の項目を追跡するフィルタを使ってそれをしました:
uniqueArray = sortedArray.filter(function(e) {
if(e==this.last)
return false;
this.last=e; return true;
},{last:null});
これで、集合を使って重複を取り除き、それらを配列に戻すことができます。
var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];
console.log([...new Set(names)])
これを行うには、 Ramda.js という機能的なJavaScriptライブラリを使用できます。
var unique = R.uniq([1, 2, 1, 3, 1, 4])
console.log(unique)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
このスクリプトは配列を変更し、重複した値を除外します。それは数字と文字列で動作します。
https://jsfiddle.net/qsdL6y5j/1/ /
Array.prototype.getUnique = function () {
var unique = this.filter(function (elem, pos) {
return this.indexOf(elem) == pos;
}.bind(this));
this.length = 0;
this.splice(0, 0, unique);
}
var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
duplicates.getUnique();
alert(duplicates);
このバージョンでは、代わりに、元の値を保持したまま一意の値を持つ新しい配列を返すことができます(単にtrueを渡します)。
https://jsfiddle.net/dj7qxyL7/ /
Array.prototype.getUnique = function (createArray) {
createArray = createArray === true ? true : false;
var temp = JSON.stringify(this);
temp = JSON.parse(temp);
if (createArray) {
var unique = temp.filter(function (elem, pos) {
return temp.indexOf(elem) == pos;
}.bind(this));
return unique;
}
else {
var unique = this.filter(function (elem, pos) {
return this.indexOf(elem) == pos;
}.bind(this));
this.length = 0;
this.splice(0, 0, unique);
}
}
var duplicates = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
console.log('++++ ovveride')
duplicates.getUnique();
console.log(duplicates);
console.log('++++ new array')
var duplicates2 = [0, 0, 1, 1, 2, 3, 1, 1, 0, 4, 4];
var unique = duplicates2.getUnique(true);
console.log(unique);
console.log('++++ original')
console.log(duplicates2);
Browser support:
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) 1.5 (1.8) 9 (Yes) (Yes)
Selectorを受け付けるバージョンは、かなり速くて簡潔であるべきです。
function unique(xs, f) {
var seen = {};
return xs.filter(function(x) {
var fx = (f && f(x)) || x;
return !seen[fx] && (seen[fx] = 1);
});
}
これはES6関数で、オブジェクトの配列から重複を取り除き、指定されたオブジェクトプロパティでフィルタリングします
function dedupe(arr = [], fnCheck = _ => _) {
const set = new Set();
let len = arr.length;
for (let i = 0; i < len; i++) {
const primitive = fnCheck(arr[i]);
if (set.has(primitive)) {
// duplicate, cut it
arr.splice(i, 1);
i--;
len--;
} else {
// new item, add it
set.add(primitive);
}
}
return arr;
}
const test = [
{video:{slug: "a"}},
{video:{slug: "a"}},
{video:{slug: "b"}},
{video:{slug: "c"}},
{video:{slug: "c"}}
]
console.log(dedupe(test, x => x.video.slug));
// [{video:{slug: "a"}}, {video:{slug: "b"}}, {video:{slug: "c"}}]
あなたがユニークな値を言うとき、私には、それはデータセットに一度だけ現れた値を意味します。
以下はvalues配列をフィルタリングし、与えられた値の最初と最後のインデックスが等しいことを確認します。インデックスが等しい場合、値は一度だけ現れなければならないことを意味します。
var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];
var unique = values.filter(function(value) {
return values.indexOf(value) === values.lastIndexOf(value);
});
console.log(unique); // [3, 6]
私が質問を誤解したというフィードバックに基づいて、これはvalues配列からユニークで重複しない値を返す代替アプローチです。
var values = [1, 2, 3, 4, 5, 2, 4, 6, 2, 1, 5];
var unique = values.reduce(function(unique, value) {
return unique.indexOf(value) === -1 ? unique.concat([value]) : unique;
}, []);
console.log(unique); // [1, 2, 3, 4, 5, 6]
@sergeyzのソリューションと似ていますが、矢印関数やarray.includes
などのより簡潔な形式を使用することでよりコンパクトになります。 警告:JSlintは論理orまたはカンマの使用により文句を言います。 (ただし、それでも完全に有効なJavaScript)
my_array.reduce((a,k)=>(a.includes(k)||a.Push(k),a),[])
多くの人がすでに使用について言及しています...
[...new Set(arr)];
これは素晴らしい解決策ですが、私の好みは.filter
で動作する解決策です。私の意見では、フィルターは一意の値を取得するより自然な方法です。重複を効果的に削除し、配列から要素を削除することがまさにフィルターの目的です。また、.map
、.reduce
、およびその他の.filter
呼び出しからチェーンを解除できます。このソリューションを考案しました...
const unique = () => {
let cache;
return (elem, index, array) => {
if (!cache) cache = new Set(array);
return cache.delete(elem);
};
};
myArray.filter(unique());
警告は、閉鎖が必要なことですが、これは価値のあるトレードオフだと思います。パフォーマンスの面では、.filter
を使用する他のソリューションよりもパフォーマンスが優れていますが、[...new Set(arr)]
よりもパフォーマンスが劣ります。
私のgithubパッケージも参照してください youneek
上記のObjectの答えは、Objectsを使った私のユースケースでは私にはうまくいかないようです。
私はそれを次のように修正しました:
var j = {};
this.forEach( function(v) {
var typ = typeof v;
var v = (typ === 'object') ? JSON.stringify(v) : v;
j[v + '::' + typ] = v;
});
return Object.keys(j).map(function(v){
if ( v.indexOf('::object') > -1 ) {
return JSON.parse(j[v]);
}
return j[v];
});
これは、オブジェクト、配列、値が混在する配列、ブール値などに対して正しく機能するようになりました.
この解決方法は非常に高速であるはずであり、多くの場合にうまくいくでしょう。
Object.keys関数を使う
var indexArray = ["hi","welcome","welcome",1,-9];
var keyArray = {};
indexArray.forEach(function(item){ keyArray[item]=null; });
var uniqueArray = Object.keys(keyArray);
時々、私はオブジェクトの配列からユニークな出現を得る必要があります。 LodashはNiceヘルパーのように思えますが、配列をフィルタリングすることがプロジェクトに依存関係を追加することを正当化するとは思わない。
2つのオブジェクトの比較が、プロパティ(idなど)を比較するときに生じると仮定しましょう。
const a = [{id: 3}, {id: 4}, {id: 3}, {id: 5}, {id: 5}, {id: 5}];
私たち全員が1行のスニペットが大好きなので、ここでそれがどのように行われることができるかです:
a.reduce((acc, curr) => acc.find(e => e.id === curr.id) ? acc : [...acc, curr], [])
もしあなたがオブジェクトの配列を持っていて、uniqueBy
関数が欲しいなら、例えばidフィールドによって:
function uniqueBy(field, arr) {
return arr.reduce((acc, curr) => {
const exists = acc.find(v => v[field] === curr[field]);
return exists ? acc : acc.concat(curr);
}, [])
}
オブジェクト内で繰り返しidを持つオブジェクトを配列から削除できる簡単な例があります
let data = new Array({id: 1},{id: 2},{id: 3},{id: 1},{id: 3});
let unique = [];
let tempArr = [];
console.log('before', data);
data.forEach((value, index) => {
if (unique.indexOf(value.id) === -1) {
unique.Push(value.id);
} else {
tempArr.Push(index);
}
});
tempArr.reverse();
tempArr.forEach(ele => {
data.splice(ele, 1);
});
console.log(data);
順序が重要でない場合は、ハッシュを作成してキーを取得して一意の配列を作成できます。
var ar = [1,3,4,5,5,6,5,6,2,1];
var uarEle = {};
links.forEach(function(a){ uarEle[a] = 1; });
var uar = keys(uarEle)
uarはユニークな配列要素を持つことになります。
私が私の特定のユースケースのためにそれを書いたという理由だけでもう一つの答え。私はとにかく配列をソートしていましたが、ソートしていれば、それを使用して重複排除することができます。
私のソートは私の特定のデータ型を扱っていることに注意してください、あなたが持っている要素の種類の種類に応じて異なる種類が必要かもしれません。
var sortAndDedup = function(array) {
array.sort(function(a,b){
if(isNaN(a) && isNaN(b)) { return a > b ? 1 : (a < b ? -1 : 0); }
if(isNaN(a)) { return 1; }
if(isNaN(b)) { return -1; }
return a-b;
});
var newArray = [];
var len = array.length;
for(var i=0; i<len; i++){
if(i === 0 || array[i] != array[i-1]){
newArray.Push(array[i]);
}
}
};
文字列には.toString()を使用してください。
var givenvalues = [1,2,3,3,4,5,6];
var values = [];
for(var i=0; i<givenvalues.length; i++)
{
if(values.indexOf(givenvalues[i]) == -1)
{
values[values.length] = givenvalues[i];
}
}
私はJoeytje50のjsperf上のコードを見て、いくつかの選択肢を比較しました。彼のコードには多くの小さな誤字があり、それがパフォーマンスと正確さに違いをもたらしました。
さらに重要なことに、彼は非常に小さなアレイでテストしています。私は1000の整数で配列を作りました。各整数は0から1000の間のランダムな整数の100倍でした。これは平均で約1000/e = 368の重複になります。結果は jsperf にあります。
これは、効率が必要とされる可能性がある場所の、はるかに現実的なシナリオです。これらの変更は、クレームに劇的な変更を加えます(具体的に言うと、最速として宣伝されているコードはどこにも速くはありません)。明らかに勝者はハッシングテクニックが使われているところです
Array.prototype.getUnique3 = function(){
var u = Object.create(null), a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(this[i] in u) continue;
a.Push(this[i]);
u[this[i]] = 1;
}
return a.length;
}
var a = [1,4,2,7,1,5,9,2,4,7,2]
var b = {}, c = {};
var len = a.length;
for(var i=0;i<len;i++){
a[i] in c ? delete b[a[i]] : b[a[i]] = true;
c[a[i]] = true;
}
// b contains all unique elements
結果を得るために、配列のヘルパー関数reduce()とsome()を利用することができます。私のコードスニペットをチェックしてください:
var arrayWithDuplicates = [0, 0, 1, 2, 3, 3, 4, 4, 'a', 'a', '', '', null, null];
var arrayWithUniqueValues = arrayWithDuplicates
.reduce((previous, item) => {
if(!previous.some(element => element === item)) {
previous.Push(item)
}
return previous;
}, []);
console.log('arrayWithUniqueValues', arrayWithUniqueValues)
未定義の値やNULL値は、ほとんどの場合必要ないので除外する.
const uniques = myArray.filter(e => e).filter((e, i, a) => a.indexOf(e) === i);
または
const uniques = [...new Set(myArray.filter(e => e))];