JavaScriptシリーズ--8種類の【配列除去】方法のまとめ

7704 ワード

はじめに
配列が重いのはありふれた問題ですが、時々他のものを弾きます.
二重循環
この方法は最も一般的で,最も原始的な方法である.
//    :    
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // res    
    var res = [];
    for(var i = 0, length = arr.length; i < length; i++){
        for(var j = 0, length2 = res.length; j < length2; j++){
            if(arr[i] === res[j]){
                break;
            }
        }
        if(j == length2){
            res.push(arr[i])
        }
    }
    return res;
}

unique(array);  //[1, "1", "2", 2]
考え方:二層循環法は、循環入れ子を使用し、外側の層はarrであり、内側の層はresであり、arr[i]の値がres[j]の値に等しい場合、現在のループから飛び出す.同じでない場合、要素が唯一であることを説明する.この場合、jの値はresの長さに等しく、この判断によって、resに値を付加する.
長所:相性がいい
短所:時間複雑度o(n 2)
三、indexOf方法
考え方:indexOfを使って内部層の循環を簡略化する.
//    :indexOf      
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // res    
    var res = [];
    for(var i = 0, length = arr.length; i < length; i++){
       var current = arr[i];
       if(res.indexOf(current) === -1){
           res.push(current);
       }
    }
    return res;
}

unique(array);   //[1, "1", "2", 2]
長所:時間の複雑さが下がる
短所:ブラウザによってはindexOfメソッドがサポートされていない場合があります.時間複雑度o(n 2)
四、並べ替え後、元に戻す
考え方:ファーストクラスのsortを使って配列を並べ替えます.このように同じ値が並べられます.現在の要素が前の要素と同じかどうかを判断するだけで、同じ説明を繰り返します.違いはresに加えます.
//    :     
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // res    
    var res = [];
    var sortedArray = arr.concat().sort();
    console.log(sortedArray, '-=-=-=-=-=-=')
    var current;
    for(var i = 0, length = sortedArray.length; i < length; i++){
        //                    
       if(!i || current !== sortedArray[i]){
           res.push(sortedArray[i]);
       }
       current = sortedArray[i];
    }
    return res;
}

unique(array);   //[1, "1", 1, "2", 2]
利点:順序付けされた配列は再分割されており、この方法の効率はindexOfを使用するより高い.時間複雑度o(n)
短所:配列の順序を変更しましたが、徹底していないものがあります.
注意:sort関数のデフォルトの並べ替えはUnicodeです.srotメソッドはデフォルトではアルファベットに並べ替えができます.sortが並べ替えの際に暗黙的な変換があり、並べ替えの対象を文字列に変換し、sortを並べ替える時には1と'1'が同じで、unicodeによってサイズが比較されるので、「1」、「1」、「2」、「2」が現れます.
注意:配列がarray.co ncat()操作された後、元の配列がコピーされています.コピーされた新しい配列は元の配列に影響しません.
五、ES 5を使うfilter
考え方:filterを使って外層循環を簡略化する
1、indexOfを使用して、内部層の循環を簡略化する.
//    :filter + indexOf
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // res    
    var res = arr.filter(function(item, index, arr){
        return arr.indexOf(item) === index;
    })
    return res;
}

unique(array);   //[1, "1", "2", 2]
2、並べ替えの重い方法
//    :filter + sort
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // res    
    var res = arr.concat().sort().filter(function(item, index, arr){
        return !index ||  item !==arr[index -1]
    })
    return res;
}

unique(array);   //[1, "1", 1, "2", 2]
以上述べましたが、ソトの並び替えには暗黙的な転換があります.
長所:簡潔で、思考も巧みで、直観的で分かりやすく、filterを使って外層の循環を簡略化します.
短所:IE 9以下のブラウザはサポートされていません.時間複雑度o(n*2)
六、Objectのキーが正しい問題
構想:空いているObjectオブジェクトを利用して、配列の値をObjectのkeyに保存します.例えばObject[value]=trueです.ループ判定の時、Object[value]が存在すれば、この値が重複したと説明します.
//    :Object   
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    // obj    
    var obj= {};
    var res = arr.filter(function(item, index, arr){
        if(obj.hasOwnProperty(item)) return false;
        else {
            return obj[item] = true;
        }
    })
    return res;
}

unique(array);   //[1, "2"]
その後、1と'1'は違っていますが、この方法では同じ値と判断されます.キーパッドの対中は文字列しかないので、隠し変換が行われます.ソートソート時の変換と同じです.typeof item+itemで文字列を作成してkeyの値として避けることができます.
//   
function unique(arr){
    // obj    
    var obj= {};
    var res = arr.filter(function(item, index, arr){
        if(obj.hasOwnProperty(typeof item + item)) return false;
        else {
            return obj[typeof item + item] = true;
        }
    })
    return res;
}

unique(array);   //[1, "1", "2", 2]
利点:ハスOwnPropertyは対象の属性の存在性検査方法です.オブジェクトの属性はhashテーブルに基づいて実装でき、したがって属性に対する方法の時間複雑度はO(1)に達する.filterは配列反復の方法であり、内部はforサイクルであり、複雑度O(n)である.全体の時間複雑度O(n).
短所:互換性のないIE 9以下のブラウザ
七、レデュース高次関数
includes()メソッドは、1つの配列が指定された値を含むかどうかを判断し、場合によってはtrueに戻る.そうでなければfalseに戻る.
//    :reduce    
var array = [1,1,'1','2','1',1,2]
function unique(arr){
    let newArr = arr.reduce((pre,cur)=>{
        if(!pre.includes(cur)){
            return pre.concat(cur)
        }else{
            return pre
        }
    },[]);
    return newArr;
}
console.log(unique(array));// [1, "1", "2", 2]
利点:高次関数の高度な使い方.
短所:互換性の問題です.オブジェクト配列はincludes法を使って検出できません.includes大文字と小文字を区別します.
八、ES 6のSetデータ構造
ES 6標準はますます良くなっているとしか言えません.Setデータ構造を使用してもいいです.ES 6にはsetデータ構造が提供されています.配列に似ています.メンバー値は全部唯一で、重複していません.
//    :ES6 set
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    return Array.from(new Set(arr));
}

unique(array);   //[1, "1", "2", 2]
拡張演算子を使うこともできます.
//   
var array = [1,1,'1','2','1',1,2]

function unique(arr){
    return  [...new Set(arr)];
}

unique(array);   //[1, "1", "2", 2]
もっと簡単に書いてください
//    
var array = [1,1,'1','2','1',1,2]

const unique = arr => [...new Set(arr)];

unique(array);   //[1, "1", "2", 2]
利点:ES 6文法は簡単で効率的です.
短所:互換性の問題に加えてバベルコンパイルを使うのは問題ではないです.
九、ES 6のMapデータ構造
//    :ES6 Map + filter
var array = [1,1,'1','2','1',1,2];

function unique(arr){
    var current = new Map();
    var res = arr.filter(function(item, index, arr){
        if(current.has(item)){
            return false;
        }else{
            return current.set(item, 1);
        }
    })
    return res;
}

unique(array);   //[1, "1", "2", 2]
考え方:mapの方法setとhasを使って、hasの方法でこのkeyが存在するかどうかを判断します.もし値がないならば、mapの中にkey-valueを保存します.
注意:最新のES 6仕様は、新しいデータタイプMapを導入しています.オブジェクト内のキーは文字列のみの問題を解決するために、他の基本データタイプはキーとして使用できます.
利点:ES 6文法は簡単で効率的です.
短所:互換性の問題に加えてバベルコンパイルを使うのは問題ではないです.
十、特殊データタイプの比較
var str1 = '1';
var str2 = new String('1');

console.log(str1 == str2); // true
console.log(str1 === str2); // false

console.log(null == null); // true
console.log(null === null); // true

console.log(undefined == undefined); // true
console.log(undefined === undefined); // true

console.log(NaN == NaN); // false
console.log(NaN === NaN); // false

console.log(/a/ == /a/); // false
console.log(/a/ === /a/); // false

console.log({} == {}); // false
console.log({} === {}); // false
くりを見ます
var arr = [1, 2, NaN];
arr.indexOf(NaN); // -1
理由:indexOfの下側はやはり==を使って判断します.NAN==NANの結果はfalseですから、indexOfを使ってもNANという要素は見つけられません.
栗をもう一つ見ます
function unique(array) {
   return Array.from(new Set(array));
}
console.log(unique([NaN, NaN])) // [NaN]
Setでは、NAN==NANはfalseですが、この2つの要素は重複しています.
十一、後話
配列の重い性能を最適化して、それから長い間考えてもObjectキーのペアの性能だけを書いて、他の引用タイプを判断することができますが、性能はn^2以内に安定しています.
自分で答えてください.
現在の時間の複雑さからO(n)までの方法:
(1)Objectキーの値は正しいです.実質はハスOwnProptyのhash表です.
(2)ES 6のset、mapのデータ構造
(3)レデュース高次関数
【注:私はsaucxsです.song Eagleとも言います.松宝はコードを書きます.文章はsau交流学習コミュニティ(https://www.mwcxs.top)で始まります.毎日もっと素晴らしい内容を読むことに注目しています.】