次のようなJavaScript配列があります。
var myData=['237','124','255','124','366','255'];
配列要素は一意でソートされる必要があります。
myData[0]='124';
myData[1]='237';
myData[2]='255';
myData[3]='366';
配列のメンバーは整数のように見えますですが、整数ではありませんです。
var myData[0]=num.toString();
//...and so on.
JavaScriptでこれらすべてのタスクを実行する方法はありますか?
これは実際には非常に簡単です。値が最初にソートされている場合、一意の値を見つける方がはるかに簡単です。
function sort_unique(arr) {
if (arr.length === 0) return arr;
arr = arr.sort(function (a, b) { return a*1 - b*1; });
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) { //Start loop at 1: arr[0] can never be a duplicate
if (arr[i-1] !== arr[i]) {
ret.Push(arr[i]);
}
}
return ret;
}
console.log(sort_unique(['237','124','255','124','366','255']));
//["124", "237", "255", "366"]
これは、事前に関数を定義できない状況(ブックマークレットなど)で適切な場合があります。
myData.sort().filter(function(el,i,a){return i===a.indexOf(el)})
function sort_unique(arr) {
return arr.sort().filter(function(el,i,a) {
return (i==a.indexOf(el));
});
}
Array.protoype.reduce()
を使用した私の(より現代的な)アプローチを次に示します。
[2, 1, 2, 3].reduce((a, x) => a.includes(x) ? a : [...a, x], []).sort()
// returns [1, 2, 3]
編集:コメントで指摘されているより高性能なバージョン:
arr.sort().filter((x, i, a) => !i || x != a[i-1])
どうですか:
array.sort().filter(function(elem, index, arr) {
return index == arr.length - 1 || arr[index + 1] != elem
})
これは@loostroの回答に似ていますが、各要素の配列を繰り返して最初に見つかったことを確認するindexOfを使用する代わりに、次の要素が現在の要素と異なることを確認します。
nderscore のような外部ライブラリを使用してみてください
var f = _.compose(_.uniq, function(array) {
return _.sortBy(array, _.identity);
});
var sortedUnique = f(array);
これは _.compose
、 _.uniq
、 _.sortBy
、 _.identity
ライブを参照してください 例
それは何をしていますか?
配列を受け取り、一意でないエントリが削除されたソート済み配列を返す関数が必要です。この関数は2つのことを行う必要があります。並べ替えと配列の一意化です。
これは作曲に適した仕事なので、独自の&並べ替え機能を一緒に作曲します。 _.uniq
は1つの引数で配列に適用できるため、_.compose
に渡されます
_.sortBy関数には、ソート条件付き関数が必要です。値を返す関数が必要であり、配列はその値でソートされます。順序付けする値は配列内の値なので、_。identity関数を渡すことができます。
これで、(配列を取得して一意の配列を返す)関数と(配列を取得し、値でソートされたソート済み配列を返す)関数の構成ができました。
配列に構成を適用するだけで、一意にソートされた配列ができます。
この関数は、3つ以上の重複値に対して失敗しません。
function unique(arr) {
var a = [];
var l = arr.length;
for(var i=0; i<l; i++) {
for(var j=i+1; j<l; j++) {
// If a[i] is found later in the array
if (arr[i] === arr[j])
j = ++i;
}
a.Push(arr[i]);
}
return a;
};
冗長な「リターン」アレイ、ECMA5ビルトイン(私はかなり確信しています!)はなく、読みやすいです。
function removeDuplicates(target_array) {
target_array.sort();
var i = 0;
while(i < target_array.length) {
if(target_array[i] === target_array[i+1]) {
target_array.splice(i+1,1);
}
else {
i += 1;
}
}
return target_array;
}
カスタムソート関数を使用する方法
//func has to return 0 in the case in which they are equal
sort_unique = function(arr,func) {
func = func || function (a, b) {
return a*1 - b*1;
};
arr = arr.sort(func);
var ret = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (func(arr[i-1],arr[i]) != 0)
ret.Push(arr[i]);
}
}
return ret;
}
例:オブジェクトの配列の降順
MyArray = sort_unique(MyArray , function(a,b){
return b.iterator_internal*1 - a.iterator_internal*1;
});
このタスクを実行するための最速かつシンプルな方法。
const N = Math.pow(8, 8)
let data = Array.from({length: N}, () => Math.floor(Math.random() * N))
let newData = {}
let len = data.length
// the magic
while (len--) {
newData[data[len]] = true
}
さまざまな理由でこの回答を投稿するつもりです。重複をパージするこの手法は、私が現在約1か月ほど前に取り組んでいるFlashのプロジェクトで取り上げたものです。
オブジェクトを作成し、各配列項目を利用してキーと値の両方でオブジェクトを埋めます。重複キーは破棄されるため、重複キーは削除されます。
var nums = [1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10];
var newNums = purgeArray(nums);
function purgeArray(ar)
{
var obj = {};
var temp = [];
for(var i=0;i<ar.length;i++)
{
obj[ar[i]] = ar[i];
}
for (var item in obj)
{
temp.Push(obj[item]);
}
return temp;
}
他にも5つの答えがありますので、ソート関数を投稿する必要はありません。
O [N ^ 2]のソリューションは悪いです。特にデータが既にソートされている場合、重複を削除するために2つのネストされたループを行う必要はありません。 1つのループと前の要素との比較がうまくいきます。
Sort()のO []を使用した簡単なソリューションで十分です。私の解決策は次のとおりです。
function sortUnique(arr, compareFunction) {
let sorted = arr.sort(compareFunction);
let result = sorted.filter(compareFunction
? function(val, i, a) { return (i == 0 || compareFunction(a[i-1], val) != 0); }
: function(val, i, a) { return (i == 0 || a[i-1] !== val); }
);
return result;
}
ところで、Array.sortUnique()メソッドを持つために次のようなことができます:
Array.prototype.sortUnique = function(compareFunction) {return sortUnique(this, compareFunction); }
さらに、sort()は、compare()関数が0(等しい要素)を返す場合に2番目の要素を削除するように変更できますが、そのコードは乱雑になる可能性があります(飛行中のループ境界を修正する必要があります)。さらに、インタープリター言語で独自のsort()関数を作成することは避けてください。パフォーマンスが低下する可能性が最も高いからです。したがって、この追加はECMA 2019+の検討対象です。
以下は、O(N)
を使用した単純な1つのライナーです。
それから
> Object.keys([{}].concat(['a', 'b', 'a']).reduce((l,r) => l[r] = l ))
[ 'a', 'b' ]
説明
元のデータセット、外部機能から入ってくると仮定
let data = ['a', 'b', 'a']
配列の前にオブジェクトを追加したい
let setup = [{}].concat(data)
次に、配列を単一の値に縮小します。
前の手順では、この手順ですべての値をキーとしてそのオブジェクトに貼り付けることができるように、オブジェクトを配列に追加しました。最終結果は、一意のキーセットを持つオブジェクトです。
let reduced = setup.reduce((l,r) => l[r] = l)
l[r] = l
なぜなら、javascriptでは、代入ステートメントが式として使用されると、代入式の値が返されるからです。
次に、そのオブジェクトのキーを取得します
let keys = Object.keys(setup)
これは元の配列の一意の値のセットです
['a', 'b']
function sort()は、数字が同じ数字の場合にのみ有効です。例:
var myData = ["3","11","1","2"]
戻ります;
var myData = ["1","11","2","3"]
そしてここでmrmonkingtonからの機能の改善
myData.sort().sort(function(a,b){return a - b;}).filter(function(el,i,a){if(i==a.indexOf(el) & el.length>0)return 1;return 0;})
上記の関数は空の配列も削除し、以下のデモをチェックアウトできます
http://jsbin.com/ahojip/2/edit
// Another way, that does not rearrange the original Array
// and spends a little less time handling duplicates.
function uniqueSort(arr, sortby){
var A1= arr.slice();
A1= typeof sortby== 'function'? A1.sort(sortby): A1.sort();
var last= A1.shift(), next, A2= [last];
while(A1.length){
next= A1.shift();
while(next=== last) next= A1.shift();
if(next!=undefined){
A2[A2.length]= next;
last= next;
}
}
return A2;
}
var myData= ['237','124','255','124','366','255','100','1000'];
uniqueSort(myData,function(a,b){return a-b})
// the ordinary sort() returns the same array as the number sort here,
// but some strings of digits do not sort so nicely numerical.