Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions benchmarks/performance/flattenObject-map.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { bench, describe } from 'vitest';
import { flattenObject } from '../../src/object/flattenObject.ts';

// Create nested objects for testing
function createNestedObject(depth: number, width: number) {
const obj: any = {};

for (let i = 0; i < width; i++) {
const key = `key${i}`;

if (depth > 1) {
obj[key] = createNestedObject(depth - 1, width);
} else {
obj[key] = `value${i}`;
}
}

return obj;
}

// Real-world translation-like data structure
const translationLikeData = {
welcome: {
title: 'Welcome to our app',
subtitle: 'Get started today',
buttons: {
login: 'Login',
signup: 'Sign Up',
forgot: 'Forgot Password',
},
},
navigation: {
home: 'Home',
about: 'About',
contact: 'Contact',
settings: {
profile: 'Profile',
preferences: 'Preferences',
security: 'Security',
notifications: {
email: 'Email',
push: 'Push',
sms: 'SMS',
},
},
},
errors: {
validation: {
required: 'This field is required',
email: 'Invalid email format',
password: 'Password too weak',
confirm: 'Passwords do not match',
},
network: ['Connection failed', 'Timeout error', 'Server error'],
auth: {
unauthorized: 'Unauthorized access',
forbidden: 'Access forbidden',
expired: 'Session expired',
},
},
features: {
premium: {
analytics: 'Advanced Analytics',
support: 'Priority Support',
storage: 'Unlimited Storage',
},
free: {
basic: 'Basic Features',
limited: 'Limited Storage',
},
},
};

describe('flattenObject Map conversion performance', () => {
bench('legacy: flattenObject + Object.entries + new Map', () => {
new Map(Object.entries(flattenObject(translationLikeData)));
});

bench('new: flattenObject with Map target', () => {
flattenObject(translationLikeData, new Map());
});
});

describe('flattenObject Map conversion - large data', () => {
const largeNestedObject = createNestedObject(4, 10); // depth 4, 10 keys per level

bench('legacy (large): flattenObject + Object.entries + new Map', () => {
new Map(Object.entries(flattenObject(largeNestedObject)));
});

bench('new (large): flattenObject with Map target', () => {
flattenObject(largeNestedObject, new Map());
});
});

describe('flattenObject Map conversion - very large data', () => {
const veryLargeNestedObject = createNestedObject(5, 20); // depth 5, 20 keys per level

bench('legacy (very large): flattenObject + Object.entries + new Map', () => {
new Map(Object.entries(flattenObject(veryLargeNestedObject)));
});

bench('new (very large): flattenObject with Map target', () => {
flattenObject(veryLargeNestedObject, new Map());
});
});

describe('flattenObject Map with custom delimiter', () => {
bench('legacy: flattenObject with delimiter + Object.entries + new Map', () => {
new Map(Object.entries(flattenObject(translationLikeData, { delimiter: '_' })));
});

bench('new: flattenObject with delimiter and Map target', () => {
flattenObject(translationLikeData, { delimiter: '_', target: new Map() });
});
});
44 changes: 40 additions & 4 deletions docs/ja/reference/object/flattenObject.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
# flattenObject

ネストされたオブジェクトを単純なオブジェクトに平坦化します
ネストされたオブジェクトを単純なオブジェクトに平坦化するか、Mapに直接変換します

- `Array`は平坦化されます。
- `Buffer`や`TypedArray`のような純粋なオブジェクトでないものは平坦化されません。

## インターフェース

```typescript
function flattenObject(object: object, { delimiter = '.' }: FlattenObjectOptions = {}): Record<string, any>;
// Record<string, any>を返す
function flattenObject(object: object, options?: { delimiter?: string }): Record<string, any>;

// Map<string, any>を返す(レガシー構文)
function flattenObject(object: object, target: Map<string, any>): Map<string, any>;

// Map<string, any>を返す(区切り文字付き)
function flattenObject(object: object, options: { delimiter?: string; target: Map<string, any> }): Map<string, any>;
```

### パラメータ

- `object` (`object`): 平坦化するオブジェクト。
- `delimiter` (`string`): ネストされたキーの区切り文字。デフォルトは `'.'`。
- `options` (`object`, オプション): オプションオブジェクト。
- `delimiter` (`string`): ネストされたキーの区切り文字。デフォルトは `'.'`。
- `target` (`Map<string, any>`): 平坦化されたキーと値のペアで満たすMap。

### 戻り値

(`T`): 平坦化されたオブジェクト
(`Record<string, any> | Map<string, any>`): 平坦化されたオブジェクトまたはMap

## 例

### 基本的な使用法(Record)

```typescript
const nestedObject = {
a: {
Expand All @@ -42,6 +53,8 @@ console.log(flattened);
// }
```

### カスタム区切り文字(Record)

```typescript
const flattened = flattenObject(nestedObject, { delimiter: '/' });
console.log(flattened);
Expand All @@ -52,3 +65,26 @@ console.log(flattened);
// 'd/1': 3
// }
```

### Mapターゲット(レガシー構文)

```typescript
const map = flattenObject(nestedObject, new Map());
console.log(map);
// 出力: Map { 'a.b.c' => 1, 'd.0' => 2, 'd.1' => 3 }

// 値へのアクセス
console.log(map.get('a.b.c')); // 1
console.log(map.size); // 3
```

### Map + カスタム区切り文字

```typescript
const customMap = flattenObject(nestedObject, {
delimiter: '_',
target: new Map(),
});
console.log(customMap);
// 出力: Map { 'a_b_c' => 1, 'd_0' => 2, 'd_1' => 3 }
```
44 changes: 40 additions & 4 deletions docs/ko/reference/object/flattenObject.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
# flattenObject

중첩된 객체를 단순한 객체로 평탄화해요.
중첩된 객체를 단순한 객체로 평탄화하거나 Map으로 직접 변환해요.

- `Array`는 평탄화돼요.
- 순수 객체가 아닌 `Buffer`나 `TypedArray`는 평탄화되지 않아요.

## 인터페이스

```typescript
function flattenObject(object: object, { delimiter = '.' }: FlattenObjectOptions = {}): Record<string, any>;
// Record<string, any> 반환
function flattenObject(object: object, options?: { delimiter?: string }): Record<string, any>;

// Map<string, any> 반환 (기존 문법)
function flattenObject(object: object, target: Map<string, any>): Map<string, any>;

// Map<string, any> 반환 (구분자 포함)
function flattenObject(object: object, options: { delimiter?: string; target: Map<string, any> }): Map<string, any>;
```

### 파라미터

- `object` (`object`): 평탄화할 객체.
- `delimiter` (`string`): 중첩된 키의 구분자. 기본값은 `.`.
- `options` (`object`, 선택): 옵션 객체.
- `delimiter` (`string`): 중첩된 키의 구분자. 기본값은 `.`.
- `target` (`Map<string, any>`): 평탄화된 키-값 쌍으로 채울 Map.

### 반환 값

(`T`): 평탄화된 객체.
(`Record<string, any> | Map<string, any>`): 평탄화된 객체 또는 Map.

## 예시

### 기본 사용법 (Record)

```typescript
const nestedObject = {
a: {
Expand All @@ -42,6 +53,8 @@ console.log(flattened);
// }
```

### 구분자 지정 (Record)

```typescript
const flattened = flattenObject(nestedObject, { delimiter: '/' });
console.log(flattened);
Expand All @@ -52,3 +65,26 @@ console.log(flattened);
// 'd/1': 3
// }
```

### Map 대상 (기존 문법)

```typescript
const map = flattenObject(nestedObject, new Map());
console.log(map);
// Output: Map { 'a.b.c' => 1, 'd.0' => 2, 'd.1' => 3 }

// 값 접근
console.log(map.get('a.b.c')); // 1
console.log(map.size); // 3
```

### Map + 구분자 지정

```typescript
const customMap = flattenObject(nestedObject, {
delimiter: '_',
target: new Map(),
});
console.log(customMap);
// Output: Map { 'a_b_c' => 1, 'd_0' => 2, 'd_1' => 3 }
```
56 changes: 52 additions & 4 deletions docs/reference/object/flattenObject.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
# flattenObject

Flattens a nested object into a single-level object with dot-separated keys.
Flattens a nested object into a single-level object with dot-separated keys or directly into a Map.

- `Array`s are flattened.
- Non-plain objects, like `Buffer`s or `TypedArray`s, are not flattened.

## Signature

```typescript
function flattenObject(object: object, { delimiter = '.' }: FlattenObjectOptions = {}): Record<string, any>;
// Return Record<string, any>
function flattenObject(object: object, options?: { delimiter?: string }): Record<string, any>;

// Return Map<string, any> (legacy syntax)
function flattenObject(object: object, target: Map<string, any>): Map<string, any>;

// Return Map<string, any> (with custom delimiter)
function flattenObject(object: object, options: { delimiter?: string; target: Map<string, any> }): Map<string, any>;
```

### Parameters

- `object` (`object`): The object to flatten.
- `delimiter` (`string`): The delimiter to use between nested keys. Defaults to `'.'`.
- `options` (`object`, optional): The options object.
- `delimiter` (`string`): The delimiter to use between nested keys. Defaults to `'.'`.
- `target` (`Map<string, any>`): The target Map to populate with flattened key-value pairs.

### Returns

(`T`): The flattened object.
(`Record<string, any> | Map<string, any>`): The flattened object or Map.

## Examples

### Basic Usage (Record)

```typescript
const nestedObject = {
a: {
Expand All @@ -42,6 +53,8 @@ console.log(flattened);
// }
```

### Custom Delimiter (Record)

```typescript
const flattened = flattenObject(nestedObject, { delimiter: '/' });
console.log(flattened);
Expand All @@ -52,3 +65,38 @@ console.log(flattened);
// 'd/1': 3
// }
```

### Map Target (Legacy Syntax)

```typescript
const map = flattenObject(nestedObject, new Map());
console.log(map);
// Output: Map { 'a.b.c' => 1, 'd.0' => 2, 'd.1' => 3 }

// Access values
console.log(map.get('a.b.c')); // 1
console.log(map.size); // 3
```

### Map with Custom Delimiter

```typescript
const customMap = flattenObject(nestedObject, {
delimiter: '_',
target: new Map(),
});
console.log(customMap);
// Output: Map { 'a_b_c' => 1, 'd_0' => 2, 'd_1' => 3 }
```

### Performance Comparison

Using Map targets provides better performance compared to converting Records to Maps:

```typescript
// Slower: Object → Array → Map (3 steps)
const slowMap = new Map(Object.entries(flattenObject(largeObject)));

// Faster: Object → Map (1 step)
const fastMap = flattenObject(largeObject, new Map());
```
Loading