web-dev-qa-db-ja.com

JavaScript配列内のすべての固有値を取得する(重複を削除する)

私は、一意であることを確認するために必要な数の配列を持っています。私はインターネット上で以下のコードスニペットを見つけました、そしてそれは配列がそれにゼロを持つまでうまく働きます。私は この他のスクリプト こちら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;
}

重複した質問からのより多くの回答:

同様の質問:

987
Mottie

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のような追加のライブラリがなくても機能します。

値が混在する配列に対しても機能します。

ネイティブメソッドfilterindexOfをサポートしていない古いブラウザ(<ie9)では、 filterindexOf のMDNドキュメントに回避策があります。

最後に出現した値を保持したい場合は、単純にindexOflastIndexOfに置き換えます。 

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 にコメントのヒントをありがとう。

1876
TLindig

ES6/ES2015用の更新された回答 Set を使用した場合の単一行の解決策は、

var items = [4,5,4,6,3,4,5,2,23,1,4,4,4]
var uniqueItems = Array.from(new Set(items))

どちらが返る 

[4, 5, 6, 3, 2, 23, 1]

le_m が示唆しているように、これは spread演算子 を使って短縮することもできます。

var uniqueItems = [...new Set(items)]
642
A.T.

underscore.js を使用することもできます。

console.log(_.uniq([1, 2, 1, 3, 1, 4]));
<script src="http://underscorejs.org/underscore-min.js"></script>

これが返されます:

[1, 2, 3, 4]
126
kornfridge

この質問にはすでに30以上の答えがあることを私は理解しています。しかし、私は最初に既存のすべての答えを読み、私自身の研究をしました。

すべての答えを4つの可能な解決策に分けました。

  1. ES6の新機能を使う:[...new Set( [1, 1, 2] )];
  2. 重複を防ぐためにオブジェクト{ }を使う
  3. ヘルパー配列[ ]を使う
  4. filter + indexOfを使う

これが回答に含まれているサンプルコードです。

ES6の新機能を使う:[...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スプレッドシートでは入手できないため、テストできません。

これがテストの結果です。 enter image description here

ハッシュを使っているので、オブジェクト{ }を使っているコードが勝つことを期待していました。そのため、ChromeとIEでテストがこのアルゴリズムに対して最良の結果を示したことをうれしく思います。 コード の@rabに感謝します。

117
Max Makhrov

One Liner、純粋なJavaScript

ES6の構文の場合

list = list.filter((x, i, a) => a.indexOf(x) == i)

x --> item in array
i --> index of item
a --> array reference, (in this case "list")

enter image description here

ES5の構文で

list = list.filter(function (x, i, a) { 
    return a.indexOf(x) == i; 
});

ブラウザの互換性 :IE9 +

52
Vamsi

私はそれ以来jQueryを使うNiceメソッドを見つけました

arr = $.grep(arr, function(v, k){
    return $.inArray(v ,arr) === k;
});

注:このコードは、 Paul Irishのアヒルのパンチポストから引っ張られた - 私は信用を与えるのを忘れていた:

50
Mottie

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を学ぶためのリソース:

45
Torsten Becker

最も簡単な解決策:

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

32
Pedro L.

これを行うための最も簡単で、かつ 最速 (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;
}

これはまた 上記の方法よりも速い ほとんどの非クロム製ブラウザで。

30
Joeytje50

パフォーマンスのみ!このコードは、おそらくここにあるすべてのコードよりも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

デモhttp://jsfiddle.net/46S7g/

注:古い配列は、この操作の後に破棄/一意になります。

上記のコードを読むことができない場合は、JavaScriptの本を読むか、短いコードについて説明します。 https://stackoverflow.com/a/21353032/24507

一部はindexOfを使用しています...しないでください... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfh

空の配列の場合

!array.length||toUnique(array); 
29
cocco

ここでの答えの多くは初心者には役に立たないかもしれません。配列を重複排除するのが難しい場合は、プロトタイプチェーン、あるいは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という名前になります。

好きな配列の名前を渡すだけです。

24
Seth Holladay
["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;
 }, []);
19
sergeyz

このプロトタイプ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"]を生成します。

17

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];
12
chinmayan

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など)での開発には最適です。

12
Cœur

これは、0がJavaScriptでは誤った値であるためです。

配列の値が0またはその他の偽の値の場合、this[i]は偽になります。

10
Luca Matteis

プロトタイプフレームワークを使用している場合は、「for」ループを実行する必要はありません。 http://www.prototypejs.org/api/array/uniq を次のように使用できます。

var a = Array.uniq();  

これにより、重複のない重複配列が生成されます。私はあなたの質問に遭遇しました。 

uniq()

私が使った 

サイズ()

そして私の簡単な結果がありました。 p.s入力ミスして申し訳ありません。

編集:あなたが未定義のレコードをエスケープしたい場合は追加することができます 

コンパクト() 

前に、このように:

var a = Array.compact().uniq();  
10
Decebal
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
}
9
ephemient

奇妙なことに、これまでには示唆されていませんでした..配列内のオブジェクトキー(以下のid)で重複を削除するには、次のようにします。

const uniqArray = array.filter((obj, idx, arr) => (
  arr.findIndex((o) => o.id === obj.id) === idx
)) 
6
daviestar

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
  )
6
Dan Fox

簡単な方法で一意の配列値を見つける

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

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]
5
Frosty Z

逆の問題を解決するには、配列をロードするときに重複しないようにすると便利です。 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]を渡します

5
Le Droid

魔法

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

5

ハッシュキーをシリアル化すると、これがオブジェクトに対して機能するようになるのに役立ちます。

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

knockoutjs を使用している場合

ko.utils.arrayGetDistinctValues()

ところで、すべてのko.utils.array*ユーティリティを見てきました。

3

追加の依存関係があっても問題ない場合、またはコードベースにすでにライブラリの1つがある場合は、LoDash(またはUnderscore)を使用して、配列から重複したものを削除できます。

使用法

まだコードベースに持っていない場合は、npmを使ってインストールします。

npm install lodash

その後、次のように使用してください。

import _ from 'lodash';
let idArray = _.uniq ([
    1,
    2,
    3,
    3,
    3
]);
console.dir(idArray);

でる:  

[ 1, 2, 3 ]
3
NikeshPathania

sugar.jsを使うこともできます:

[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"}]
3
kornfridge

Es6ベースのソリューション...

var arr = [2,3,4,2,3,4,2];
const result = [...new Set(arr)];
console.log(result);
2
Vahid Akhtar

これを見てください。 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
});
2
ilgam

オブジェクトキーを使ってユニークな配列を作るために、私は以下を試してみました

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]を返します

2
rab

これが配列からユニークなアイテムを取得する最も簡単な方法だと思います。

var arr = [1,2,4,1,4];
arr = Array.from(new Set(arr))
console.log(arr)
2
Riajul Islam

強力な reduce メソッド( ≥5.1 )を利用できる場合は、次のようにして試すことができます。

Array.prototype.uniq = function() {
  return this.reduce(function(sofar, cur) {
    return sofar.indexOf(cur) < 0 ? sofar.concat([cur]) : sofar;
  }, []);
};

これは最も効率的な実装ではありません(indexOfチェックのため、最悪の場合はリスト全体を調べます)。効率が重要な場合は、発生の「履歴」を何らかのランダムアクセス構造(たとえば{})に保持し、代わりにそれらをキー入力できます。それが基本的に 最も投票された答え がすることなので、例としてそれをチェックしてください。

2
Hunan Rostomyan
[...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]
2
SumanP

これはうまくいくでしょう。

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

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

(これが最も簡単な方法です)

2
BazSTR

他の答えを基にして、戦略を選択するためにオプションのフラグを取る別の変種があります(最初に出現するか最後に保つ):

拡張なし 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]
2
Mrchief

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関数?

2

重複排除では、通常、指定されたタイプの等価演算子が必要です。ただし、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"}]

これらのコンビネータにより、あらゆる種類の重複排除の問題に非常に柔軟に対応できます。それは断食法ではなく、最も表現力があり、最も一般的なものです。

2
bob

私は配列から重複したidプロパティを持つオブジェクトを削除する必要があるところで私はわずかに異なる問題を抱えていた。これはうまくいった。

let objArr = [ { id: '123' }, { id: '123' }, { id: '456' } ];

objArr = objArr.reduce( ( acc, cur ) => [
    ...acc.filter( ( obj ) => obj.id !== cur.id ), cur
], [] );
2
shunryu111

私は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]
1
tjacks3
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]
1
user2718726

私はこれがすでに死に答えられていることを知っています...しかし... 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>

1
pgee70

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

これは純粋ではない、それは配列を変更しますが、これは最速のものです。あなたの方が速いなら、それからコメントを書いてください;)

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"]
1
webdeb
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);
1
Junaid Khan

山のためのさらに別の解決策。

私は最近ソートされたリストをユニークにする必要があり、私はこのようなオブジェクトの前の項目を追跡するフィルタを使ってそれをしました:

uniqueArray = sortedArray.filter(function(e) { 
    if(e==this.last) 
      return false; 
    this.last=e; return true;  
  },{last:null});
1
pix

これで、集合を使って重複を取り除き、それらを配列に戻すことができます。

var names = ["Mike","Matt","Nancy", "Matt","Adam","Jenny","Nancy","Carl"];

console.log([...new Set(names)])
1
Krishnadas PC

これを行うには、 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>

1
Morris S

このスクリプトは配列を変更し、重複した値を除外します。それは数字と文字列で動作します。

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)
1
GibboK

Selectorを受け付けるバージョンは、かなり速くて簡潔であるべきです。

function unique(xs, f) {
  var seen = {};
  return xs.filter(function(x) {
    var fx = (f && f(x)) || x;
    return !seen[fx] && (seen[fx] = 1);
  });
}
1
Grozz

これは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"}}]
1
Andrei

あなたがユニークな値を言うとき、私には、それはデータセットに一度だけ現れた値を意味します。

以下は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]

1
fubar

@sergeyzのソリューションと似ていますが、矢印関数やarray.includesなどのより簡潔な形式を使用することでよりコンパクトになります。 警告:JSlintは論理orまたはカンマの使用により文句を言います。 (ただし、それでも完全に有効なJavaScript)

my_array.reduce((a,k)=>(a.includes(k)||a.Push(k),a),[])
1
John Smith

多くの人がすでに使用について言及しています...

[...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

0
Nizmox

上記の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];
});

これは、オブジェクト、配列、値が混在する配列、ブール値などに対して正しく機能するようになりました.

0
user3591464

この解決方法は非常に高速であるはずであり、多くの場合にうまくいくでしょう。

  1. 添字付き配列項目をオブジェクトキーに変換する
  2. Object.keys関数を使う

    var indexArray = ["hi","welcome","welcome",1,-9];
    var keyArray = {};
    indexArray.forEach(function(item){ keyArray[item]=null; });
    var uniqueArray = Object.keys(keyArray);
    
0

時々、私はオブジェクトの配列からユニークな出現を得る必要があります。 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], [])

0

もしあなたがオブジェクトの配列を持っていて、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);
   }, [])
}
0
Ben

オブジェクト内で繰り返し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);
0
Shridhar Sagari

順序が重要でない場合は、ハッシュを作成してキーを取得して一意の配列を作成できます。

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はユニークな配列要素を持つことになります。

0
Kishore Relangi

私が私の特定のユースケースのためにそれを書いたという理由だけでもう一つの答え。私はとにかく配列をソートしていましたが、ソートしていれば、それを使用して重複排除することができます。

私のソートは私の特定のデータ型を扱っていることに注意してください、あなたが持っている要素の種類の種類に応じて異なる種類が必要かもしれません。

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]);
    }
  }
};
0
PaulL

文字列には.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];
    }
}
0
Phani CR

私は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;
}
0
Roobie Nuby
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
0
rajesh

結果を得るために、配列のヘルパー関数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))];
0
LEMUEL ADANE