-
Notifications
You must be signed in to change notification settings - Fork 544
feat(object): implement sortKeys #1674
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # sortKeys | ||
|
|
||
| キーがソートされた新しいオブジェクトを作成します。 | ||
|
|
||
| ```typescript | ||
| const sorted = sortKeys(object, compare?); | ||
| ``` | ||
|
|
||
| ## 使い方 | ||
|
|
||
| ### `sortKeys(object, compare?)` | ||
|
|
||
| オブジェクトのキーを一定の順序にソートしたい場合に`sortKeys`を使用します。デフォルトではキーがアルファベット順にソートされるため、シリアライズ、比較、表示などの用途に便利です。 | ||
|
|
||
| ```typescript | ||
| import { sortKeys } from 'es-toolkit/object'; | ||
|
|
||
| const sorted = sortKeys({ c: 3, a: 1, b: 2 }); | ||
| // { a: 1, b: 2, c: 3 } | ||
| ``` | ||
|
|
||
| カスタム比較関数を渡して、異なるソート方式を使用することもできます。 | ||
|
|
||
| ```typescript | ||
| // 逆アルファベット順にソートします | ||
| const reversed = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a)); | ||
| // { c: 3, b: 2, a: 1 } | ||
| ``` | ||
|
|
||
| 値はネストされたオブジェクトや配列を含め、そのまま保持されます。 | ||
|
|
||
| ```typescript | ||
| const obj = { z: [1, 2], a: { nested: true }, m: 'hello' }; | ||
| const sorted = sortKeys(obj); | ||
| // { a: { nested: true }, m: 'hello', z: [1, 2] } | ||
| ``` | ||
|
|
||
| #### パラメータ | ||
|
|
||
| - `object` (`T`): キーをソートするオブジェクトです。 | ||
| - `compare` (`(a: string, b: string) => number`, オプション): キーのソートに使用するカスタム比較関数です。デフォルトはアルファベット順です。 | ||
|
|
||
| #### 戻り値 | ||
|
|
||
| (`T`): キーがソートされた新しいオブジェクトを返します。 | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,45 @@ | ||||||
| # sortKeys | ||||||
|
|
||||||
| 키가 정렬된 새로운 객체를 생성해요. | ||||||
|
|
||||||
| ```typescript | ||||||
| const sorted = sortKeys(object, compare?); | ||||||
|
||||||
| const sorted = sortKeys(object, compare?); | |
| const sorted = sortKeys(object, compare); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,45 @@ | ||||||
| # sortKeys | ||||||
|
|
||||||
| Creates a new object with the keys sorted. | ||||||
|
|
||||||
| ```typescript | ||||||
| const sorted = sortKeys(object, compare?); | ||||||
|
||||||
| const sorted = sortKeys(object, compare?); | |
| const sorted = sortKeys(object); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,45 @@ | ||||||
| # sortKeys | ||||||
|
|
||||||
| 创建一个键已排序的新对象。 | ||||||
|
|
||||||
| ```typescript | ||||||
| const sorted = sortKeys(object, compare?); | ||||||
|
||||||
| const sorted = sortKeys(object, compare?); | |
| const sorted = sortKeys(object); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import { describe, expect, it } from 'vitest'; | ||
| import { sortKeys } from './sortKeys'; | ||
|
|
||
| describe('sortKeys', () => { | ||
| it('should sort object keys alphabetically by default', () => { | ||
| const result = sortKeys({ c: 3, a: 1, b: 2 }); | ||
| expect(Object.keys(result)).toEqual(['a', 'b', 'c']); | ||
| expect(result).toEqual({ a: 1, b: 2, c: 3 }); | ||
| }); | ||
|
|
||
| it('should sort keys with a custom compare function', () => { | ||
| const result = sortKeys({ a: 1, b: 2, c: 3 }, (a, b) => b.localeCompare(a)); | ||
| expect(Object.keys(result)).toEqual(['c', 'b', 'a']); | ||
| }); | ||
|
Comment on lines
+4
to
+14
|
||
|
|
||
| it('should return an empty object for empty input', () => { | ||
| const result = sortKeys({}); | ||
| expect(result).toEqual({}); | ||
| expect(Object.keys(result)).toEqual([]); | ||
| }); | ||
|
|
||
| it('should preserve values after sorting', () => { | ||
| const obj = { z: [1, 2], a: { nested: true }, m: 'hello' }; | ||
| const result = sortKeys(obj); | ||
|
|
||
| expect(Object.keys(result)).toEqual(['a', 'm', 'z']); | ||
| expect(result.z).toEqual([1, 2]); | ||
| expect(result.a).toEqual({ nested: true }); | ||
| expect(result.m).toBe('hello'); | ||
| }); | ||
|
|
||
| it('should handle numeric string keys', () => { | ||
| const result = sortKeys({ 3: 'c', 1: 'a', 2: 'b' }); | ||
| expect(Object.keys(result)).toEqual(['1', '2', '3']); | ||
| }); | ||
|
|
||
| it('should not mutate the original object', () => { | ||
| const obj = { b: 2, a: 1 }; | ||
| const result = sortKeys(obj); | ||
|
|
||
| expect(result).not.toBe(obj); | ||
| expect(Object.keys(obj)).toEqual(['b', 'a']); | ||
| }); | ||
|
|
||
| it('should handle single-key objects', () => { | ||
| const result = sortKeys({ only: 1 }); | ||
| expect(Object.keys(result)).toEqual(['only']); | ||
| expect(result).toEqual({ only: 1 }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||
| /** | ||||||||||||||
| * Creates a new object with the keys sorted. | ||||||||||||||
| * | ||||||||||||||
| * The keys are sorted alphabetically by default, but a custom compare function can be provided. | ||||||||||||||
| * | ||||||||||||||
| * @template T - The type of the object. | ||||||||||||||
| * @param {T} object - The object to sort keys from. | ||||||||||||||
| * @param {(a: string, b: string) => number} [compare] - A custom compare function for sorting keys. | ||||||||||||||
| * @returns {T} A new object with the keys sorted. | ||||||||||||||
| * | ||||||||||||||
| * @example | ||||||||||||||
| * sortKeys({ b: 2, a: 1, c: 3 }); | ||||||||||||||
| * // => { a: 1, b: 2, c: 3 } | ||||||||||||||
| * | ||||||||||||||
| * @example | ||||||||||||||
| * sortKeys({ b: 2, a: 1, c: 3 }, (a, b) => b.localeCompare(a)); | ||||||||||||||
| * // => { c: 3, b: 2, a: 1 } | ||||||||||||||
| */ | ||||||||||||||
| export function sortKeys<T extends Record<string, any>>(object: T, compare?: (a: string, b: string) => number): T { | ||||||||||||||
| const sortedKeys = Object.keys(object).sort(compare); | ||||||||||||||
|
|
||||||||||||||
| const result = {} as Record<string, any>; | ||||||||||||||
|
|
||||||||||||||
| for (let i = 0; i < sortedKeys.length; i++) { | ||||||||||||||
| const key = sortedKeys[i]; | ||||||||||||||
|
||||||||||||||
| const key = sortedKeys[i]; | |
| const key = sortedKeys[i]; | |
| // Skip unsafe keys that could lead to prototype pollution. | |
| if (key === '__proto__' || key === 'constructor' || key === 'prototype') { | |
| continue; | |
| } |
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.
The TypeScript snippet
sortKeys(object, compare?)is not valid TypeScript syntax (the?marker can’t be used in a call expression). Update the snippet to a valid call (e.g.sortKeys(object)andsortKeys(object, compare)).