-
-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(array): Object.groupBy
静的メソッドを追加
#1749
Conversation
✅ Deploy Preview for js-primer ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
const array = [1, 2, 3, 4, 5]; | ||
const grouped = Object.groupBy(array, (currentValue) => { | ||
// currentValueが偶数なら"even"、そうでないなら"odd"の配列に追加される | ||
return currentValue % 2 === 0 ? "even" : "odd"; | ||
}); | ||
console.log(grouped.even); // => [2, 4] | ||
console.log(grouped.odd); // => [1, 3, 5] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
node
Welcome to Node.js v22.4.1.
Type ".help" for more information.
> assert.deepStrictEqual({}, {})
undefined
> assert.deepStrictEqual(Object.create(null), {})
Uncaught AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected
+ [Object: null prototype] {}
- {}
at REPL16:1:8
at ContextifyScript.runInThisContext (node:vm:136:12)
at REPLServer.defaultEval (node:repl:598:22)
at bound (node:domain:432:15)
at REPLServer.runBound [as eval] (node:domain:443:12)
at REPLServer.onLine (node:repl:927:10)
at REPLServer.emit (node:events:532:35)
at REPLServer.emit (node:domain:488:12)
at [_onLine] [as _onLine] (node:internal/readline/interface:416:12)
at [_line] [as _line] (node:internal/readline/interface:887:18) {
generatedMessage: true,
code: 'ERR_ASSERTION',
actual: [Object: null prototype] {},
expected: {},
operator: 'deepStrictEqual'
}
Object.groupByは Object.create(null)を返すのプロパティ同士の比較にした。
https://tc39.es/proposal-array-grouping/#sec-object.groupby
Node.js v20.11.1以上とnpm 10.2.4以上が必要です。 | ||
Node.js v22.4.1以上とnpm 10.8.2以上が必要です。 | ||
|
||
``` | ||
$ node -v | ||
v20.11.1 | ||
v22.4.1 | ||
$ npm -v | ||
10.2.4 | ||
10.8.2 | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
book.jsonはまた別で更新。テストがNode.js 22じゃないと全てはpassしないので(20でもignoreされるだけで動きはする)
@@ -29,12 +29,12 @@ jobs: | |||
runs-on: ubuntu-latest | |||
strategy: | |||
matrix: | |||
node-version: [18, 20] | |||
node-version: [20, 22.5.1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://nodejs.org/en/blog/release/v22.5.1
22.5.0は動かないため。
しかし、`reduce`メソッドは使い方がやや複雜であるため、可能なら避けたほうが読みやすいコードとなりやすいです。 | ||
ES2024では、`Object.groupBy`静的メソッドが追加され、配列からグループ分けしたオブジェクトを作成できるようになっています。 | ||
|
||
`Object.groupBy`静的メソッド[^1]は、第1引数に配列を、第2引数にグループ分けの条件を返すコールバック関数を渡します。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.groupBy
の第一引数は配列に限らずiterableならなんでも処理することができます1。このページが配列の解説なので意図的にこのような表現にしているのかもしれませんが、もし本全体の設計としてここでiterableについて言及するのが自然だと判断できるようであれば、そのようにしたほうが良いかもしれません。
Footnotes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます。
proposal-array-groupingでもArray限定で始まってたのでそこまで意識してなかったですが、色々考えてみてここではiterableについて触れる必要性はあまりないかなと思いました。
現実的な理由としては、配列以外のiterableを渡すユースケースがあまり思いつかない(setはあるかもしれないが)のと、章の構成的に他のiterableがこの章より前に説明されてるものが配列以外はないことなどがあります。(文字列はあるが実用性がない)
iterable対応といった場合にも、無限iteratorには対応してないので、ちょっと中途半端な気がしています。
- Grouping via iterator methods? tc39/proposal-array-grouping#51
- https://github.com/tc39/notes/blob/main/meetings/2022-11/nov-29.md#array-grouping-webcompat-issue
// infinity iterator
const infinityIterator = function*() {
let i = 0;
while (true) {
yield i++;
}
};
const grouped = Object.groupBy(infinityIterator(), value => {
if (value % 2 === 0) {
return 'even';
}
return 'odd';
});
console.log(grouped);
なので、具体的にはArrayとMap/Setを受け付けるという感じになる気がしますが、 Object.groupBy(map, …)
はここだと書けない感じがします。そのため、おそらく配列の章におく場合は省略するのが妥当かなという感じがしました。
おそらくIterator Helpersが入った時にIteratorが本格的に意識される気がするので、その時にiterable関係を章を独立させたり考え直すのがいいんじゃなかなと思ってます。
iterableを扱う同様のものとして Object.fromEntries
と Array.from
がありますが、これもiterableを扱うものというよりは、ユースケース(Map to Object、Array-like to Array)がメインな感じがしますね。
💭 iterableといったときに無限と有限があんまり意識できないので、MDNはリストとか言ったり、コレクションとかいうみたいな整理も合わせて必要そう。iteratorだけで切り出すとちょっと難しい部分かもしれない。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
サンプルコードとしてiterableを受け付けることは省くのが妥当な気はするけど(書籍の目的外になる)、シグネチャの説明として"配列を含むiterableなオブジェクト"てきな表現にするのはありかもしれない。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1754 で対応しました
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます。おっしゃるとおり、現実的にはObject.groupByに渡される値は配列がメインですので、もし言及されるとしても軽く触れる程度で良いと思います。
Object.groupBy
静的メソッドを追加
概要
ES2024では、配列の要素をグループ分けしたオブジェクトを作成する
Object.groupBy
静的メソッドが追加されています。配列の要素をグループ化を簡潔に書けるようになっています。
Array.prototype.groupBy
のようなArrayのメソッドではないのは、既存のprototype拡張をしていたライブラリとの競合を避けるためです。最初は、
Array.prototype.groupBy
メソッドとして提案されていましたが、既存のウェブサイトとの互換性の問題が見つかったため、Object.groupBy
静的メソッドに変更されました。変更されたページ
変更内容
Object.groupBy
静的メソッドの説明を追加関連
cc @koralle