19

重複しているオブジェクトを配列から削除する効率的な方法を見つけようとしており、最も効率的な答えを探しています。私はインターネットを見回して、すべてがプリミティブデータを使用しているようです...または大規模な配列に対してスケーラブルではありません。これは私の現在の実装であり、改善することができ、ラベルを回避したいと考えています。

 Test.prototype.unique = function (arr, artist, title, cb) {
        console.log(arr.length);
        var n, y, x, i, r;
        r = [];      
        o: for (i = 0, n = arr.length; i < n; i++) {

          for (x = 0, y = r.length; x < y; x++) {

                if (r[x].artist == arr[i].artist && r[x].title == arr[i].title) {
                    continue o;
                }
            }
            r.push(arr[i]);
        }

        cb(r);
    };

配列は次のようになります。

[{title: sky, artist: jon}, {title: rain, artist: Paul}, ....]

順序は問題ではありませんが、並べ替えによって効率が向上する場合は、挑戦します...

o がラベルであることを知らない人にとっては、新しい配列にプッシュするのではなく、ループに戻ると言っているだけです。

純粋な JavaScript はライブラリを使用しないでください。

これまでの回答:

以下の回答に対するパフォーマンス テスト: http://jsperf.com/remove-duplicates-for-loops

4

9 に答える 9

30

なるほど、問題は複雑さが 2 乗されていることです。それを行うためのトリックが1つあります。それは、単に「連想配列」を使用することです。

配列を取得してループし、配列の値をキーとして連想配列に追加できます。重複したキーは許可されないため、重複は自動的に削除されます。

比較するときにタイトルとアーティストを探しているので、実際には次のようなものを使用できます。

var arrResult = {};
for (i = 0, n = arr.length; i < n; i++) {
    var item = arr[i];
    arrResult[ item.title + " - " + item.artist ] = item;
}

次に、arrResult をもう一度ループして、配列を再作成します。

var i = 0;
var nonDuplicatedArray = [];    
for(var item in arrResult) {
    nonDuplicatedArray[i++] = arrResult[item];
}

Paul のコメントを含むように更新されました。ありがとう!

于 2013-10-21T18:07:08.573 に答える
3

ここに私のために働く解決策があります。

ヘルパー関数:

// sorts an array of objects according to one field
// call like this: sortObjArray(myArray, "name" );
// it will modify the input array
sortObjArray = function(arr, field) {
    arr.sort(
        function compare(a,b) {
            if (a[field] < b[field])
                return -1;
            if (a[field] > b[field])
                return 1;
            return 0;
        }
    );
}

// call like this: uniqueDishes = removeDuplicatesFromObjArray(dishes, "dishName");
// it will NOT modify the input array
// input array MUST be sorted by the same field (asc or desc doesn't matter)
removeDuplicatesFromObjArray = function(arr, field) {
    var u = [];
    arr.reduce(function (a, b) {
        if (a[field] !== b[field]) u.push(b);
        return b;
    }, []);
    return u;
}

そして、単に呼び出します:

        sortObjArray(dishes, "name");
        dishes = removeDuplicatesFromObjArray(dishes, "name");
于 2015-09-25T13:23:14.770 に答える
2

基本的な sort-then-unique 実装、フィドルHERE :

function unique(arr) {
    var comparer = function compareObject(a, b) {
        if (a.title == b.title) {
            if (a.artist < b.artist) {
                return -1;
            } else if (a.artist > b.artist) {
                return 1;
            } else {
                return 0;
            }
        } else {
            if (a.title < b.title) {
                return -1;
            } else {
                return 1;
            }
        }
    }

    arr.sort(comparer);
    console.log("Sorted: " + JSON.stringify(arr));
    for (var i = 0; i < arr.length - 1; ++i) {
        if (comparer(arr[i], arr[i+1]) === 0) {
            arr.splice(i, 1);
            console.log("Splicing: " + JSON.stringify(arr));
        }
    }
    return arr;
}

これは最も効率的である場合もそうでない場合もあり、完全にスケーラブルであるべきです。いくつかの s を追加console.logしたので、動作する様子を確認できます。

編集

関数が使用するスペースを節約するためにfor、最後にそのループを実行しましたが、一意の結果のみを適切に見つけられなかったようです (単純な jsfiddle テストに合格したにもかかわらず)。for私のループを次のものに置き換えてみてください:

var checker;
var uniqueResults = [];
for (var i = 0; i < arr.length; ++i) {
    if (!checker || comparer(checker, arr[i]) != 0) {
        checker = arr[i];
        uniqueResults.push(checker);
    }
}
return uniqueResults;
于 2013-10-21T18:25:18.550 に答える
1

私はこの機能を使用しています。ソートは行いませんが、結果を生成します。決して測定しないので、パフォーマンスについては言えません。

var unique = function(a){
    var seen = [], result = [];
    for(var len = a.length, i = len-1; i >= 0; i--){
        if(!seen[a[i]]){
            seen[a[i]] = true;
            result.push(a[i]);
        }
    }
    return result;
}

var ar = [1,2,3,1,1,1,1,1,"", "","","", "a", "b"]; console.log(unique(ar));// これにより [1,2,3,"", "a", "b"] すべての一意の要素が生成されます。

于 2015-03-03T14:15:36.067 に答える
0

アンダースコア js を使用している場合、重複オブジェクトを簡単に削除できます。 http://underscorejs.org/#uniq

于 2015-03-01T19:05:52.543 に答える