DTPab

DTPにまつわるあれこれ

配列から重複要素を削除したい

配列から重複要素を削除する関数

配列から重複要素を削除するには、filterやsetなどを使うといいそうです*1
しかし僕が使うのは当然ながらExtendScript(以下ExS)。ECMAScriptJavaScriptの標準仕様*2。以下ES)5やES2015(ES6)で登場した新しいものには対応できないのです。
そこで以下のような処理を考えました。ifindexOfも使いませんw

function removeRep (ary){
    var temp ={}, res = [];
    for (var i=0; i<ary.length; i++) temp[ary[i]] = i;
    for (key in temp) res.push (key);
    return res;
    }

関数の名前は適当に変えてください。

説明

まずはtempというオブジェクトと、resという配列を用意します。
引数として渡された配列の中身を、ひとつずつtempオブジェクトのkeyとして格納し、valueにインデックスであるiを入れています。
これはtempオブジェクトを連想配列のように利用しています。→連想配列*3
連想配列のkeyは一意ですから、

temp[ary[i]] = i;

この部分で、tempオブジェクトのプロパティ[ary[i]]がまだ存在していなければ新たに用意され、すでに存在している場合は内容が上書きされるということです。
したがって、temp[ary[i]]が存在しようがしまいが、そのプロパティにインデックスiを格納することで重複を上書きして省いてしまおう、という魂胆です。
このようにして重複を省いたtempオブジェクトを、用意しておいたres配列にひとつずつ格納してこの関数の戻り値としています。

注意点

この関数の注意点はやはり連想配列を使っているという点です。
第一に、戻り値として取得した配列の中の値は、全て文字列になります。
第二に、型を考慮しません。数値としての1と、文字列としての"1"は区別されずに重複しているとして、1がひとつだけ配列に入ります(もちろん前述のようにこれは文字列型です)。つまり、文字列に変換して同じと判断できるものは重複したとして省かれます。
以上の注意点を理解して使えば、そこそこ短い関数ですし、使いようもあるかと思います。

雑感

JS(もといExS)は動的型変換が便利な言語である反面、型については意識が薄れがちです。そこだけ注意してもらいつつ、ifindexOfも使わないちょっと変わった配列からの重複要素の削除でした。
もっといい方法が見つかれば共有したいと思います。もちろん、for文とif文をゴリゴリ使えば実装するのは容易いのですが…。
はやいとこExSもせめてES5対応してほしいですね^^;

*1:かもメモ「JS 配列の重複を取り除きたい」http://chaika.hatenablog.com/entry/2017/04/28/083000などを参考にしました

*2:https://ja.wikipedia.org/wiki/ECMAScript

*3:Ajax Tower「連想配列を使ったプロパティへの値の代入と参照」https://www.ajaxtower.jp/js/object/index4.htmlが比較的わかりやすい