並べ替えとグループ化に関する私の仮定が正しいかどうか、lodashのドキュメントから理解するのに問題があります。
SortByを使用してからgroupByを使用する場合、groupByによって生成された配列はアイテムの並べ替え順序を維持しますか?
たとえば、次の配列があるとします。
var testArray = [[5,6],[1,3],[5,4],[5,1]]
そして、これらを最初の要素でグループ化するだけでなく、これらのグループ内の2番目の要素で並べ替えてもらいたいと思います。したがって、lodashでは、次のことができると思います。
_.chain(testArray)
.sortBy(function (item) { return item[1]; })
.groupBy(function (item) { return item[0]; })
.value()
これは、私が期待するものを生み出すことになります:
{
1: [[1,3]]
5: [[5,1],[5,4],[5,6]]
}
これは単なる偶然ですか?グループ化された配列のこの順序を保証するsortByとgroupByの動作について何かありますか?ドキュメントには、sortByは安定したソートであると記載されていますが、それはgroupByにも同じように当てはまりますか?これが毎回機能するとは限らない理由はありますか?
現在の実装 の_.groupBy
は次のとおりです。
// An internal function used for aggregate "group by" operations.
var group = function(behavior) {
return function(obj, iteratee, context) {
var result = {};
iteratee = cb(iteratee, context);
_.each(obj, function(value, index) {
var key = iteratee(value, index, obj);
behavior(result, value, key);
});
return result;
};
};
// Groups the object's values by a criterion. Pass either a string attribute
// to group by, or a function that returns the criterion.
_.groupBy = group(function(result, value, key) {
if (_.has(result, key)) result[key].Push(value); else result[key] = [value];
});
基本的に、コレクション内の各アイテムを順番に繰り返し処理し(コレクションが配列のような場合、sortBy
の後になります)、キー値に基づいてそれらを配列にプッシュします。
そうです、これが_.groupBy
の「公式」特性であるかどうかはわかりませんが、配列のようなコレクションの順序は保持されており、おそらく変更される可能性は低いでしょう。
そうではありません。順序が保持されない例を次に示します。
const data = [
{
item: 'item1',
group: 'g2'
}, {
item: 'item2',
group: 'g3'
}, {
item: 'item3',
group: 'g1'
}, {
item: 'item4',
group: 'g2'
}, {
item: 'item5',
group: 'g3'
}
]
const groupedItems = _(data).groupBy(item => item.group).value()
この場合、グループの順序は次のようになります。g2、g3、g1-実際には、g1、g2、g3でソートされます。
ただし、元の配列でそれらを再ソートすることはできます。
const groupedItems = _(data)
.groupBy(item => item.group)
.sortBy(group => data.indexOf(group[0]))
.value()
これにより、アイテムの元の順序が保証されます。
関数groupByはオブジェクトを返します。オブジェクトはプロパティの順序を保存しません。 JavaScriptはオブジェクトプロパティの順序を保証しますか?
ただし、グループ配列はプッシュ機能で追加されるため、順序が節約されます。