Skip to content

Commit 746b30c

Browse files
committedJul 29, 2021
1 parent 8b64ba5 commit 746b30c

20 files changed

+243
-0
lines changed
 

‎README.md

+22
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Promise.resolve(32).then(x => console.log(x)); // => 32
112112
- [`.of` and `.from` methods on collection constructors](#of-and-from-methods-on-collection-constructors)
113113
- [`compositeKey` and `compositeSymbol`](#compositekey-and-compositesymbol)
114114
- [`Array` filtering](#array-filtering)
115+
- [`Array` grouping](#array-grouping)
115116
- [`Array` deduplication](#array-deduplication)
116117
- [Getting last item from `Array`](#getting-last-item-from-array)
117118
- [`Number.range`](#numberrange)
@@ -2292,6 +2293,27 @@ core-js/features/typed-array/filter-reject
22922293
```js
22932294
[1, 2, 3, 4, 5].filterReject(it => it % 2); // => [2, 4]
22942295
````
2296+
##### [`Array` grouping](#https://github.com/tc39/proposal-array-grouping)[⬆](#index)
2297+
Modules [`esnext.array.group-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.group-by.js) and [`esnext.typed-array.group-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.typed-array.group-by.js).
2298+
```js
2299+
class Array {
2300+
groupBy(callbackfn: (value: any, index: number, target: any) => key, thisArg?: any): { [key]: Array<mixed> };
2301+
}
2302+
2303+
class %TypedArray% {
2304+
groupBy(callbackfn: (value: number, index: number, target: %TypedArray%) => key, thisArg?: any): { [key]: %TypedArray% };
2305+
}
2306+
```
2307+
[*CommonJS entry points:*](#commonjs-api)
2308+
```
2309+
core-js/proposals/array-grouping
2310+
core-js(-pure)/features/array(/virtual)/group-by
2311+
core-js/features/typed-array/group-by
2312+
```
2313+
[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%204%2C%205%5D.groupBy(it%20%3D%3E%20it%20%25%202))%3B%20%2F%2F%20%3D%3E%20%7B%201%3A%20%5B1%2C%203%2C%205%5D%2C%200%3A%20%5B2%2C%204%5D%20%7D):
2314+
```js
2315+
[1, 2, 3, 4, 5].groupBy(it => it % 2); // => { 1: [1, 3, 5], 0: [2, 4] }
2316+
````
22952317
##### [Array deduplication](https://github.com/tc39/proposal-array-unique)[⬆](#index)
22962318
Modules [`esnext.array.unique-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.unique-by.js) and [`esnext.typed-array.unique-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.typed-array.unique-by.js)
22972319
```js

‎packages/core-js-compat/src/data.mjs

+4
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,8 @@ export const data = {
14251425
},
14261426
'esnext.array.find-last-index': {
14271427
},
1428+
'esnext.array.group-by': {
1429+
},
14281430
'esnext.array.is-template-object': {
14291431
},
14301432
'esnext.array.last-index': {
@@ -1683,6 +1685,8 @@ export const data = {
16831685
},
16841686
'esnext.typed-array.find-last-index': {
16851687
},
1688+
'esnext.typed-array.group-by': {
1689+
},
16861690
'esnext.typed-array.unique-by': {
16871691
},
16881692
'esnext.weak-map.delete-all': {

‎packages/core-js-compat/src/modules-by-versions.mjs

+2
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ export default {
9797
],
9898
3.16: [
9999
'esnext.array.filter-reject',
100+
'esnext.array.group-by',
100101
'esnext.typed-array.filter-reject',
102+
'esnext.typed-array.group-by',
101103
],
102104
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// empty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
require('../../modules/esnext.array.group-by');
2+
var entryUnbind = require('../../internals/entry-unbind');
3+
4+
module.exports = entryUnbind('Array', 'groupBy');

‎packages/core-js/features/array/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require('../../modules/esnext.array.filter-out');
66
require('../../modules/esnext.array.filter-reject');
77
require('../../modules/esnext.array.find-last');
88
require('../../modules/esnext.array.find-last-index');
9+
require('../../modules/esnext.array.group-by');
910
require('../../modules/esnext.array.is-template-object');
1011
require('../../modules/esnext.array.last-item');
1112
require('../../modules/esnext.array.last-index');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
require('../../../modules/esnext.array.group-by');
2+
var entryVirtual = require('../../../internals/entry-virtual');
3+
4+
module.exports = entryVirtual('Array').groupBy;

‎packages/core-js/features/array/virtual/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require('../../../modules/esnext.array.filter-out');
66
require('../../../modules/esnext.array.filter-reject');
77
require('../../../modules/esnext.array.find-last');
88
require('../../../modules/esnext.array.find-last-index');
9+
require('../../../modules/esnext.array.group-by');
910
require('../../../modules/esnext.array.unique-by');
1011

1112
module.exports = parent;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
var groupBy = require('../array/virtual/group-by');
2+
3+
var ArrayPrototype = Array.prototype;
4+
5+
module.exports = function (it) {
6+
var own = it.groupBy;
7+
return it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.groupBy) ? groupBy : own;
8+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('../../modules/esnext.typed-array.group-by');

‎packages/core-js/features/typed-array/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require('../../modules/esnext.typed-array.filter-out');
66
require('../../modules/esnext.typed-array.filter-reject');
77
require('../../modules/esnext.typed-array.find-last');
88
require('../../modules/esnext.typed-array.find-last-index');
9+
require('../../modules/esnext.typed-array.group-by');
910
require('../../modules/esnext.typed-array.unique-by');
1011

1112
module.exports = parent;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
var bind = require('../internals/function-bind-context');
2+
var has = require('../internals/has');
3+
var IndexedObject = require('../internals/indexed-object');
4+
var toObject = require('../internals/to-object');
5+
var toLength = require('../internals/to-length');
6+
var toPrimitive = require('../internals/to-primitive');
7+
var objectCreate = require('../internals/object-create');
8+
9+
var push = [].push;
10+
11+
module.exports = function ($this, callbackfn, that, specificCreate) {
12+
var O = toObject($this);
13+
var self = IndexedObject(O);
14+
var boundFunction = bind(callbackfn, that, 3);
15+
var target = objectCreate(null);
16+
var length = toLength(self.length);
17+
var index = 0;
18+
var value, result, array;
19+
for (;length > index; index++) {
20+
value = self[index];
21+
result = toPrimitive(boundFunction(value, index, O), 'string');
22+
if (has(target, result)) array = target[result];
23+
else target[result] = array = specificCreate ? specificCreate($this, 0) : [];
24+
push.call(array, value);
25+
} return target;
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
var $ = require('../internals/export');
3+
var $groupBy = require('../internals/array-group-by');
4+
var arraySpeciesCreate = require('../internals/array-species-create');
5+
var addToUnscopables = require('../internals/add-to-unscopables');
6+
7+
// `Array.prototype.groupBy` method
8+
// https://github.com/tc39/proposal-array-grouping
9+
$({ target: 'Array', proto: true }, {
10+
groupBy: function groupBy(callbackfn /* , thisArg */) {
11+
return $groupBy(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined, arraySpeciesCreate);
12+
}
13+
});
14+
15+
addToUnscopables('groupBy');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
3+
var $groupBy = require('../internals/array-group-by');
4+
var speciesConstructor = require('../internals/species-constructor');
5+
6+
var aTypedArray = ArrayBufferViewCore.aTypedArray;
7+
var aTypedArrayConstructor = ArrayBufferViewCore.aTypedArrayConstructor;
8+
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;
9+
10+
// `%TypedArray%.prototype.groupBy` method
11+
// https://github.com/tc39/proposal-array-grouping
12+
exportTypedArrayMethod('groupBy', function groupBy(callbackfn /* , thisArg */) {
13+
var result = $groupBy(aTypedArray(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
14+
var TypedArray = aTypedArrayConstructor(speciesConstructor(this, this.constructor));
15+
var key, array, typedArray, index, length;
16+
for (key in result) {
17+
array = result[key];
18+
length = array.length;
19+
result[key] = typedArray = new TypedArray(length);
20+
for (index = 0; index < length; index++) typedArray[index] = array[index];
21+
} return result;
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// https://github.com/tc39/proposal-array-grouping
2+
require('../modules/esnext.array.group-by');
3+
require('../modules/esnext.typed-array.group-by');

‎packages/core-js/stage/1.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require('../proposals/array-filtering');
2+
require('../proposals/array-grouping');
23
require('../proposals/array-last');
34
require('../proposals/array-unique');
45
require('../proposals/collection-methods');

‎tests/commonjs.js

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
7171
ok(typeof load('features/array/filter-reject') === 'function');
7272
ok(typeof load('features/array/flat') === 'function');
7373
ok(typeof load('features/array/flat-map') === 'function');
74+
ok(typeof load('features/array/group-by') === 'function');
7475
ok(typeof load('features/array/some') === 'function');
7576
ok(typeof load('features/array/every') === 'function');
7677
ok(typeof load('features/array/reduce') === 'function');
@@ -106,6 +107,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
106107
ok(typeof load('features/array/virtual/filter-reject') === 'function');
107108
ok(typeof load('features/array/virtual/flat') === 'function');
108109
ok(typeof load('features/array/virtual/flat-map') === 'function');
110+
ok(typeof load('features/array/virtual/group-by') === 'function');
109111
ok(typeof load('features/array/virtual/some') === 'function');
110112
ok(typeof load('features/array/virtual/every') === 'function');
111113
ok(typeof load('features/array/virtual/reduce') === 'function');
@@ -970,6 +972,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
970972
load('proposals/accessible-object-hasownproperty');
971973
load('proposals/array-filtering');
972974
load('proposals/array-find-from-last');
975+
load('proposals/array-grouping');
973976
load('proposals/array-is-template-object');
974977
load('proposals/array-last');
975978
load('proposals/array-unique');
@@ -1182,6 +1185,12 @@ for (PATH of ['core-js-pure', 'core-js']) {
11821185
ok(typeof instanceFilterReject([]) === 'function');
11831186
ok(instanceFilterReject([]).call([1, 2, 3], it => it % 2).length === 1);
11841187

1188+
const instanceGroupBy = load('features/instance/group-by');
1189+
ok(typeof instanceGroupBy === 'function');
1190+
ok(instanceGroupBy({}) === undefined);
1191+
ok(typeof instanceGroupBy([]) === 'function');
1192+
ok(instanceGroupBy([]).call([1, 2, 3], it => it % 2)[1].length === 2);
1193+
11851194
let instanceFindIndex = load('features/instance/find-index');
11861195
ok(typeof instanceFindIndex === 'function');
11871196
ok(instanceFindIndex({}) === undefined);
@@ -1710,6 +1719,7 @@ load('features/typed-array/fill');
17101719
load('features/typed-array/filter');
17111720
load('features/typed-array/filter-out');
17121721
load('features/typed-array/filter-reject');
1722+
load('features/typed-array/group-by');
17131723
load('features/typed-array/find');
17141724
load('features/typed-array/find-index');
17151725
load('features/typed-array/find-last');

‎tests/pure/esnext.array.group-by.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { STRICT } from '../helpers/constants';
2+
3+
import Symbol from 'core-js-pure/features/symbol';
4+
import groupBy from 'core-js-pure/features/array/group-by';
5+
import getPrototypeOf from 'core-js-pure/features/object/get-prototype-of';
6+
7+
QUnit.test('Array#groupBy', assert => {
8+
assert.isFunction(groupBy);
9+
let array = [1];
10+
const context = {};
11+
groupBy(array, function (value, key, that) {
12+
assert.same(arguments.length, 3, 'correct number of callback arguments');
13+
assert.same(value, 1, 'correct value in callback');
14+
assert.same(key, 0, 'correct index in callback');
15+
assert.same(that, array, 'correct link to array in callback');
16+
assert.same(this, context, 'correct callback context');
17+
}, context);
18+
assert.same(getPrototypeOf(groupBy([], it => it)), null, 'null proto');
19+
assert.deepEqual(groupBy([1, 2, 3], it => it % 2), { 1: [1, 3], 0: [2] }, '#1');
20+
assert.deepEqual(
21+
groupBy([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], it => `i${ it % 5 }`),
22+
{ i1: [1, 6, 11], i2: [2, 7, 12], i3: [3, 8], i4: [4, 9], i0: [5, 10] },
23+
'#2',
24+
);
25+
assert.deepEqual(groupBy(Array(3), it => it), { undefined: [undefined, undefined, undefined] }, '#3');
26+
if (STRICT) {
27+
assert.throws(() => groupBy(null, () => { /* empty */ }), TypeError);
28+
assert.throws(() => groupBy(undefined, () => { /* empty */ }), TypeError);
29+
}
30+
array = [1];
31+
// eslint-disable-next-line object-shorthand -- constructor
32+
array.constructor = { [Symbol.species]: function () {
33+
return { foo: 1 };
34+
} };
35+
assert.same(groupBy(array, Boolean).true.foo, 1, '@@species');
36+
});

‎tests/tests/esnext.array.group-by.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { STRICT } from '../helpers/constants';
2+
3+
const { getPrototypeOf } = Object;
4+
5+
QUnit.test('Array#groupBy', assert => {
6+
const { groupBy } = Array.prototype;
7+
assert.isFunction(groupBy);
8+
assert.arity(groupBy, 1);
9+
assert.name(groupBy, 'groupBy');
10+
assert.looksNative(groupBy);
11+
assert.nonEnumerable(Array.prototype, 'groupBy');
12+
let array = [1];
13+
const context = {};
14+
array.groupBy(function (value, key, that) {
15+
assert.same(arguments.length, 3, 'correct number of callback arguments');
16+
assert.same(value, 1, 'correct value in callback');
17+
assert.same(key, 0, 'correct index in callback');
18+
assert.same(that, array, 'correct link to array in callback');
19+
assert.same(this, context, 'correct callback context');
20+
}, context);
21+
assert.same(getPrototypeOf([].groupBy(it => it)), null, 'null proto');
22+
assert.deepEqual([1, 2, 3].groupBy(it => it % 2), { 1: [1, 3], 0: [2] }, '#1');
23+
assert.deepEqual(
24+
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].groupBy(it => `i${ it % 5 }`),
25+
{ i1: [1, 6, 11], i2: [2, 7, 12], i3: [3, 8], i4: [4, 9], i0: [5, 10] },
26+
'#2',
27+
);
28+
assert.deepEqual(Array(3).groupBy(it => it), { undefined: [undefined, undefined, undefined] }, '#3');
29+
if (STRICT) {
30+
assert.throws(() => groupBy.call(null, () => { /* empty */ }), TypeError);
31+
assert.throws(() => groupBy.call(undefined, () => { /* empty */ }), TypeError);
32+
}
33+
array = [1];
34+
// eslint-disable-next-line object-shorthand -- constructor
35+
array.constructor = { [Symbol.species]: function () {
36+
return { foo: 1 };
37+
} };
38+
assert.same(array.groupBy(Boolean).true.foo, 1, '@@species');
39+
});
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants';
2+
3+
const { getPrototypeOf } = Object;
4+
5+
if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.groupBy', assert => {
6+
// we can't implement %TypedArrayPrototype% in all engines, so run all tests for each typed array constructor
7+
for (const name in TYPED_ARRAYS) {
8+
const TypedArray = GLOBAL[name];
9+
const { groupBy } = TypedArray.prototype;
10+
assert.isFunction(groupBy, `${ name }::groupBy is function`);
11+
assert.arity(groupBy, 1, `${ name }::groupBy arity is 1`);
12+
assert.name(groupBy, 'groupBy', `${ name }::groupBy name is 'groupBy'`);
13+
assert.looksNative(groupBy, `${ name }::groupBy looks native`);
14+
const array = new TypedArray([1]);
15+
const context = {};
16+
array.groupBy(function (value, key, that) {
17+
assert.same(arguments.length, 3, 'correct number of callback arguments');
18+
assert.same(value, 1, 'correct value in callback');
19+
assert.same(key, 0, 'correct index in callback');
20+
assert.same(that, array, 'correct link to array in callback');
21+
assert.same(this, context, 'correct callback context');
22+
}, context);
23+
24+
assert.same(getPrototypeOf(new TypedArray([1]).groupBy(it => it)), null, 'null proto');
25+
assert.ok(new TypedArray([1]).groupBy(it => it)[1] instanceof TypedArray, 'instance');
26+
assert.deepEqual(
27+
new TypedArray([1, 2, 3]).groupBy(it => it % 2),
28+
{ 1: new TypedArray([1, 3]), 0: new TypedArray([2]) },
29+
'#1',
30+
);
31+
assert.deepEqual(new TypedArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).groupBy(it => `i${ it % 5 }`), {
32+
i1: new TypedArray([1, 6, 11]),
33+
i2: new TypedArray([2, 7, 12]),
34+
i3: new TypedArray([3, 8]),
35+
i4: new TypedArray([4, 9]),
36+
i0: new TypedArray([5, 10]),
37+
}, '#2');
38+
39+
assert.throws(() => groupBy.call([0], () => { /* empty */ }), "isn't generic");
40+
}
41+
});
42+

0 commit comments

Comments
 (0)
Please sign in to comment.