Skip to content
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

Merged
merged 14 commits into from
Jul 20, 2024
Merged

Conversation

azu
Copy link
Collaborator

@azu azu commented Jul 15, 2024

概要

ES2024では、配列の要素をグループ分けしたオブジェクトを作成するObject.groupBy静的メソッドが追加されています。
配列の要素をグループ化を簡潔に書けるようになっています。

Array.prototype.groupByのようなArrayのメソッドではないのは、既存のprototype拡張をしていたライブラリとの競合を避けるためです。
最初は、Array.prototype.groupByメソッドとして提案されていましたが、既存のウェブサイトとの互換性の問題が見つかったため、Object.groupBy静的メソッドに変更されました。

変更されたページ

変更内容

  • Object.groupBy静的メソッドの説明を追加

関連

cc @koralle

@azu azu linked an issue Jul 15, 2024 that may be closed by this pull request
2 tasks
@bot-user
Copy link

bot-user commented Jul 15, 2024

Deploy Preview for js-primer ready!

Name Link
🔨 Latest commit baa5f42
🔍 Latest deploy log https://app.netlify.com/sites/js-primer/deploys/669b5ec4d49f2c00080283f1
😎 Deploy Preview https://deploy-preview-1749--js-primer.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Comment on lines +1032 to +1038
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]
Copy link
Collaborator Author

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

Comment on lines -82 to 89
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
```
Copy link
Collaborator Author

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]
Copy link
Collaborator Author

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は動かないため。

@azu azu merged commit 4cbdccd into master Jul 20, 2024
13 checks passed
@azu azu deleted the feature/1716 branch July 20, 2024 07:02
@azu azu mentioned this pull request Jul 20, 2024
2 tasks
@azu azu self-assigned this Jul 20, 2024
しかし、`reduce`メソッドは使い方がやや複雜であるため、可能なら避けたほうが読みやすいコードとなりやすいです。
ES2024では、`Object.groupBy`静的メソッドが追加され、配列からグループ分けしたオブジェクトを作成できるようになっています。

`Object.groupBy`静的メソッド[^1]は、第1引数に配列を、第2引数にグループ分けの条件を返すコールバック関数を渡します。
Copy link
Contributor

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

  1. https://tc39.es/ecma262/#sec-groupby の 4

Copy link
Collaborator Author

@azu azu Jul 20, 2024

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がこの章より前に説明されてるものが配列以外はないことなどがあります。(文字列はあるが実用性がない)

image

iterable対応といった場合にも、無限iteratorには対応してないので、ちょっと中途半端な気がしています。

// 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.fromEntriesArray.from がありますが、これもiterableを扱うものというよりは、ユースケース(Map to Object、Array-like to Array)がメインな感じがしますね。

💭 iterableといったときに無限と有限があんまり意識できないので、MDNはリストとか言ったり、コレクションとかいうみたいな整理も合わせて必要そう。iteratorだけで切り出すとちょっと難しい部分かもしれない。

Copy link
Collaborator Author

@azu azu Jul 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

サンプルコードとしてiterableを受け付けることは省くのが妥当な気はするけど(書籍の目的外になる)、シグネチャの説明として"配列を含むiterableなオブジェクト"てきな表現にするのはありかもしれない。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1754 で対応しました

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。おっしゃるとおり、現実的にはObject.groupByに渡される値は配列がメインですので、もし言及されるとしても軽く触れる程度で良いと思います。

@azu azu changed the title feat(array): Object.groupBy静的メソッドを追加 feat(array): Object.groupBy 静的メソッドを追加 Aug 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ES2024: Object.groupBy/Map.groupBy
3 participants