web-dev-qa-db-ja.com

Javascript配列の並べ替えと一意

次のような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でこれらすべてのタスクを実行する方法はありますか?

50
theHack

これは実際には非常に簡単です。値が最初にソートされている場合、一意の値を見つける方がはるかに簡単です。

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"]
134
lonesomeday

これは、事前に関数を定義できない状況(ブックマークレットなど)で適切な場合があります。

myData.sort().filter(function(el,i,a){return i===a.indexOf(el)})
34
mrmonkington
function sort_unique(arr) {
    return arr.sort().filter(function(el,i,a) {
        return (i==a.indexOf(el));
    });
}
16
ioleo

これで、one行のコードで結果を達成できます。

new Set を使用して、配列を一意の値セットに減らします。文字列値を並べ替えるには、 sort メソッドを適用します。

var myData=['237','124','255','124','366','255']

var uniqueAndSorted = [...new Set(myData)].sort() 

[〜#〜] updated [〜#〜]質問の時からJavaScriptに導入された新しいメソッド用。

16
meteorBuzz

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])
13
phaux

どうですか:

array.sort().filter(function(elem, index, arr) {
  return index == arr.length - 1 || arr[index + 1] != elem
})

これは@loostroの回答に似ていますが、各要素の配列を繰り返して最初に見つかったことを確認するindexOfを使用する代わりに、次の要素が現在の要素と異なることを確認します。

8
glampr

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関数を渡すことができます。

これで、(配列を取得して一意の配列を返す)関数と(配列を取得し、値でソートされたソート済み配列を返す)関数の構成ができました。

配列に構成を適用するだけで、一意にソートされた配列ができます。

6
Raynos

この関数は、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;
};
5
Victor

冗長な「リターン」アレイ、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;
}
1
Amiga500Kid

カスタムソート関数を使用する方法

//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;
        });
1
rodi

このタスクを実行するための最速かつシンプルな方法。

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
}
0
Marshall

さまざまな理由でこの回答を投稿するつもりです。重複をパージするこの手法は、私が現在約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つの答えがありますので、ソート関数を投稿する必要はありません。

0
user1385191

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+の検討対象です。

0
iva2k

以下は、O(N)を使用した単純な1つのライナーです。

  • 最新のブラウザまたはnode.jsを使用している
  • あなたの配列は文字列です

それから

> 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']
0
justin.m.chase

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
0
ewwink
// 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.
0
kennebec