-
Notifications
You must be signed in to change notification settings - Fork 0
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: #30 add function "pick", "omit" #31
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,5 @@ | ||
--- | ||
"json-origami": minor | ||
--- | ||
|
||
feat: #30 add function "pick", "omit" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { fold } from './fold' | ||
import { unfold } from './unfold' | ||
import { includesKey } from './utils' | ||
import type { Dictionary, DeepKeyOf, OmitOption, Omit, Folded } from './type' | ||
|
||
/** | ||
* Returns an object with the specified keys removed from the object. | ||
* | ||
* @example | ||
* ```ts | ||
* const obj = { | ||
* a: 1, | ||
* b: { | ||
* c: 2, | ||
* d: [3, 4] | ||
* } | ||
* } | ||
* | ||
* const omitted = omit(obj, ['a', 'b.c']) | ||
* // omitted is | ||
* // { | ||
* // b: { | ||
* // d: [3, 4] | ||
* // } | ||
* // } | ||
* ``` | ||
* | ||
* @param obj | ||
* @param keys | ||
* @param opt | ||
*/ | ||
export function omit<D extends Dictionary, K extends DeepKeyOf<D>>( | ||
obj: D, | ||
keys: K[], | ||
opt?: OmitOption | ||
): Omit<D, K> { | ||
const folded = fold(obj) | ||
|
||
const targetKeys = new Set( | ||
Object.keys(folded).filter((k) => !keys.some((key) => includesKey(key, k, opt))) | ||
) | ||
|
||
const fixedKeyMap = Object.fromEntries( | ||
Object.entries(folded).filter(([k]) => targetKeys.has(k)) | ||
) as Folded<Dictionary> | ||
|
||
return unfold(fixedKeyMap, opt) as Dictionary | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { fold } from './fold' | ||
import { unfold } from './unfold' | ||
import { includesKey } from './utils' | ||
import type { Dictionary, DeepKeyOf, PickOption, Omit, Folded } from './type' | ||
|
||
/** | ||
* Returns an object with the specified keys picked from the object. | ||
* | ||
* @example | ||
* ```ts | ||
* const obj = { | ||
* a: 1, | ||
* b: { | ||
* c: 2, | ||
* d: [3, 4] | ||
* } | ||
* } | ||
* | ||
* const omitted = pick(obj, ['a', 'b.c']) | ||
* // omitted is | ||
* // { | ||
* // a: 1, | ||
* // b: { | ||
* // c: 2 | ||
* // } | ||
* // } | ||
* ``` | ||
* | ||
* @param obj | ||
* @param keys | ||
* @param opt | ||
*/ | ||
export function pick<D extends Dictionary, K extends DeepKeyOf<D>>( | ||
obj: D, | ||
keys: K[], | ||
opt?: PickOption | ||
): Omit<D, K> { | ||
const folded = fold(obj) | ||
|
||
const targetKeys = new Set( | ||
Object.keys(folded).filter((k) => keys.some((key) => includesKey(key, k, opt))) | ||
) | ||
|
||
const fixedKeyMap = Object.fromEntries( | ||
Object.entries(folded).filter(([k]) => targetKeys.has(k)) | ||
) as Folded<Dictionary> | ||
|
||
return unfold(fixedKeyMap, opt) as Dictionary | ||
} | ||
Comment on lines
+33
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- const targetKeys = new Set(
- Object.keys(folded).filter((k) => keys.some((key) => includesKey(key, k, opt)))
- )
+ const keySet = new Set(keys);
+ const targetKeys = new Set(
+ Object.keys(folded).filter((k) => keySet.has(k))
+ ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. includesKey は文字列の一致比較ではないため、 keySet.has とは判定結果が異なります。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mew-ton ご指摘いただきありがとうございます。 しかし、パフォーマンスの観点からは依然として改善の余地があります。 具体的には、 + const includesKeyCache = new Map();
const targetKeys = new Set(
- Object.keys(folded).filter((k) => keys.some((key) => includesKey(key, k, opt)))
+ Object.keys(folded).filter((k) => {
+ if (!includesKeyCache.has(k)) {
+ includesKeyCache.set(k, keys.some((key) => includesKey(key, k, opt)));
+ }
+ return includesKeyCache.get(k);
+ })
) この変更により、各キーに対する |
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.
omit
関数の実装は、指定されたキーをオブジェクトから削除するという目的に適しています。この関数は、まずオブジェクトをフラットな表現に変換し(fold
関数)、次に指定したキーをフィルタリングし、最後に元の構造に戻します(unfold
関数)。これらのステップは効率的であり、コードの可読性も高いです。ただし、一部のパフォーマンス改善が可能です。特に、
keys.some((key) => includesKey(key, k, opt))
の部分では、各キーに対してincludesKey
関数が呼び出されています。これは、大きなキー配列に対しては非効率的になる可能性があります。代わりに、キーをSetに変換し、その存在をチェックすることで、パフォーマンスを向上させることができます。以下に修正案を示します: