mapEntries
將對象的鍵值對映射為新的鍵值對,支持自定義轉換函數。
基礎用法
typescript
import { mapEntries } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
const mapped = mapEntries(obj, (key, value) => [key.toUpperCase(), value])
console.log(mapped) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }
語法
typescript
function mapEntries<T extends Record<string, any>, U extends Record<string, any>>(
obj: T,
fn: (key: keyof T, value: T[keyof T]) => [string, any]
): U
參數
obj
(T): 要映射的對象fn
(function): 映射函數,接收鍵和值,返回新的鍵值對數組
返回值
返回映射後的新對象。
示例
基本鍵值映射
typescript
import { mapEntries } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
// 將鍵轉換為大寫
const mapped1 = mapEntries(obj, (key, value) => [key.toUpperCase(), value])
console.log(mapped1) // { NAME: 'Alice', AGE: 25, CITY: 'Beijing' }
// 將鍵轉換為小寫
const mapped2 = mapEntries(obj, (key, value) => [key.toLowerCase(), value])
console.log(mapped2) // { name: 'Alice', age: 25, city: 'Beijing' }
自定義鍵值轉換
typescript
import { mapEntries } from 'radash'
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
// 添加前綴到鍵名
const mapped1 = mapEntries(obj, (key, value) => [`user_${key}`, value])
console.log(mapped1) // { user_name: 'Alice', user_age: 25, user_city: 'Beijing' }
// 轉換值為字符串
const mapped2 = mapEntries(obj, (key, value) => [key, String(value)])
console.log(mapped2) // { name: 'Alice', age: '25', city: 'Beijing' }
// 同時轉換鍵和值
const mapped3 = mapEntries(obj, (key, value) => [
key.toUpperCase(),
typeof value === 'string' ? value.toUpperCase() : value
])
console.log(mapped3) // { NAME: 'ALICE', AGE: 25, CITY: 'BEIJING' }
處理不同類型的值
typescript
import { mapEntries } from 'radash'
const obj = {
name: 'Alice',
age: 25,
isActive: true,
score: 95.5,
tags: ['admin', 'user']
}
// 根據值類型進行不同處理
const mapped = mapEntries(obj, (key, value) => {
if (typeof value === 'string') {
return [`${key}_str`, value.toUpperCase()]
} else if (typeof value === 'number') {
return [`${key}_num`, value * 2]
} else if (typeof value === 'boolean') {
return [`${key}_bool`, value ? 'YES' : 'NO']
} else if (Array.isArray(value)) {
return [`${key}_arr`, value.join(', ')]
}
return [key, value]
})
console.log(mapped)
// {
// name_str: 'ALICE',
// age_num: 50,
// isActive_bool: 'YES',
// score_num: 191,
// tags_arr: 'admin, user'
// }
處理空值和undefined
typescript
import { mapEntries } from 'radash'
const obj = {
name: 'Alice',
email: null,
phone: undefined,
address: ''
}
// 過濾空值並轉換鍵名
const mapped = mapEntries(obj, (key, value) => {
if (value == null) {
return [`${key}_null`, 'N/A']
}
return [key, value]
})
console.log(mapped)
// {
// name: 'Alice',
// email_null: 'N/A',
// phone_null: 'N/A',
// address: ''
// }
處理嵌套對象
typescript
import { mapEntries } from 'radash'
const obj = {
user: { name: 'Alice', age: 25 },
settings: { theme: 'dark', language: 'en' }
}
// 扁平化嵌套對象
const mapped = mapEntries(obj, (key, value) => {
if (typeof value === 'object' && value !== null) {
return Object.entries(value).map(([subKey, subValue]) => [
`${key}_${subKey}`,
subValue
])
}
return [key, value]
})
console.log(mapped)
// {
// user_name: 'Alice',
// user_age: 25,
// settings_theme: 'dark',
// settings_language: 'en'
// }
處理函數值
typescript
import { mapEntries } from 'radash'
const obj = {
name: 'Alice',
handler: () => 'hello',
validator: function() { return true },
processor: (x: number) => x * 2
}
// 轉換函數為字符串描述
const mapped = mapEntries(obj, (key, value) => {
if (typeof value === 'function') {
return [`${key}_fn`, value.toString()]
}
return [key, value]
})
console.log(mapped)
// {
// name: 'Alice',
// handler_fn: '() => \'hello\'',
// validator_fn: 'function() { return true }',
// processor_fn: '(x) => x * 2'
// }
處理日期值
typescript
import { mapEntries } from 'radash'
const obj = {
createdAt: new Date('2023-01-01'),
updatedAt: new Date('2023-12-31'),
birthday: new Date('1998-05-15')
}
// 轉換日期為ISO字符串
const mapped = mapEntries(obj, (key, value) => {
if (value instanceof Date) {
return [`${key}_iso`, value.toISOString()]
}
return [key, value]
})
console.log(mapped)
// {
// createdAt_iso: '2023-01-01T00:00:00.000Z',
// updatedAt_iso: '2023-12-31T00:00:00.000Z',
// birthday_iso: '1998-05-15T00:00:00.000Z'
// }
處理布爾值
typescript
import { mapEntries } from 'radash'
const obj = {
isActive: true,
isVerified: false,
isPremium: true,
isBlocked: false
}
// 轉換布爾值為字符串
const mapped = mapEntries(obj, (key, value) => {
if (typeof value === 'boolean') {
return [`${key}_str`, value ? 'YES' : 'NO']
}
return [key, value]
})
console.log(mapped)
// {
// isActive_str: 'YES',
// isVerified_str: 'NO',
// isPremium_str: 'YES',
// isBlocked_str: 'NO'
// }
處理數字值
typescript
import { mapEntries } from 'radash'
const obj = {
id: 1,
score: 95.5,
rating: 4.8,
count: 0,
price: -10.99
}
// 轉換數字為不同格式
const mapped = mapEntries(obj, (key, value) => {
if (typeof value === 'number') {
return [
`${key}_formatted`,
value < 0 ? `(${Math.abs(value)})` : value.toString()
]
}
return [key, value]
})
console.log(mapped)
// {
// id_formatted: '1',
// score_formatted: '95.5',
// rating_formatted: '4.8',
// count_formatted: '0',
// price_formatted: '(10.99)'
// }
處理API響應數據
typescript
import { mapEntries } from 'radash'
const apiResponse = {
status: 200,
data: { id: 1, name: 'Alice' },
meta: { timestamp: new Date(), requestId: 'req_123456' }
}
// 添加前綴並轉換值
const mapped = mapEntries(apiResponse, (key, value) => {
const newKey = `api_${key}`
if (key === 'status') {
return [newKey, value === 200 ? 'SUCCESS' : 'ERROR']
}
if (key === 'data') {
return [newKey, JSON.stringify(value)]
}
if (key === 'meta') {
return [newKey, value.timestamp.toISOString()]
}
return [newKey, value]
})
console.log(mapped)
// {
// api_status: 'SUCCESS',
// api_data: '{"id":1,"name":"Alice"}',
// api_meta: '2023-12-31T12:00:00.000Z'
// }
處理表單數據
typescript
import { mapEntries } from 'radash'
const formData = {
personal: {
firstName: 'Alice',
lastName: 'Smith',
email: 'alice@example.com'
},
address: {
street: '123 Main St',
city: 'Beijing',
country: 'China'
}
}
// 扁平化表單數據
const mapped = mapEntries(formData, (key, value) => {
if (typeof value === 'object' && value !== null) {
return Object.entries(value).map(([subKey, subValue]) => [
`${key}_${subKey}`,
subValue
])
}
return [key, value]
})
console.log(mapped)
// {
// personal_firstName: 'Alice',
// personal_lastName: 'Smith',
// personal_email: 'alice@example.com',
// address_street: '123 Main St',
// address_city: 'Beijing',
// address_country: 'China'
// }
處理錯誤對象
typescript
import { mapEntries } from 'radash'
const errorObject = {
name: 'ValidationError',
message: 'Invalid input',
details: {
field: 'email',
value: 'invalid-email',
constraints: { format: 'Must be a valid email' }
}
}
// 轉換錯誤對象為日志格式
const mapped = mapEntries(errorObject, (key, value) => {
const newKey = `error_${key}`
if (key === 'details') {
return [newKey, JSON.stringify(value)]
}
return [newKey, value]
})
console.log(mapped)
// {
// error_name: 'ValidationError',
// error_message: 'Invalid input',
// error_details: '{"field":"email","value":"invalid-email","constraints":{"format":"Must be a valid email"}}'
// }
處理日志數據
typescript
import { mapEntries } from 'radash'
const logEntry = {
timestamp: new Date(),
level: 'ERROR',
message: 'Database connection failed',
context: { userId: 123, requestId: 'req_456' },
error: { code: 'ECONNREFUSED', message: 'Connection refused' }
}
// 轉換日志數據為結構化格式
const mapped = mapEntries(logEntry, (key, value) => {
const newKey = `log_${key}`
if (value instanceof Date) {
return [newKey, value.toISOString()]
}
if (typeof value === 'object' && value !== null) {
return [newKey, JSON.stringify(value)]
}
return [newKey, value]
})
console.log(mapped)
// {
// log_timestamp: '2023-12-31T12:00:00.000Z',
// log_level: 'ERROR',
// log_message: 'Database connection failed',
// log_context: '{"userId":123,"requestId":"req_456"}',
// log_error: '{"code":"ECONNREFUSED","message":"Connection refused"}'
// }
處理數據庫查詢結果
typescript
import { mapEntries } from 'radash'
const dbResult = {
id: 1,
name: 'Product A',
category: {
id: 5,
name: 'Electronics'
},
variants: [
{ id: 101, color: 'Red', price: 99.99 },
{ id: 102, color: 'Blue', price: 89.99 }
]
}
// 轉換數據庫結果為API格式
const mapped = mapEntries(dbResult, (key, value) => {
const newKey = `db_${key}`
if (key === 'category') {
return [newKey, JSON.stringify(value)]
}
if (key === 'variants') {
return [newKey, value.length.toString()]
}
return [newKey, value]
})
console.log(mapped)
// {
// db_id: 1,
// db_name: 'Product A',
// db_category: '{"id":5,"name":"Electronics"}',
// db_variants: '2'
// }
處理配置對象
typescript
import { mapEntries } from 'radash'
const config = {
server: {
host: 'localhost',
port: 3000
},
database: {
url: 'postgresql://localhost:5432/mydb',
pool: { min: 1, max: 10 }
},
api: {
version: 'v1',
rateLimit: { windowMs: 900000, max: 100 }
}
}
// 扁平化配置對象
const mapped = mapEntries(config, (key, value) => {
if (typeof value === 'object' && value !== null) {
return Object.entries(value).map(([subKey, subValue]) => [
`${key}_${subKey}`,
subValue
])
}
return [key, value]
})
console.log(mapped)
// {
// server_host: 'localhost',
// server_port: 3000,
// database_url: 'postgresql://localhost:5432/mydb',
// database_pool: { min: 1, max: 10 },
// api_version: 'v1',
// api_rateLimit: { windowMs: 900000, max: 100 }
// }
處理空對象和邊界情況
typescript
import { mapEntries } from 'radash'
// 空對象
console.log(mapEntries({}, (key, value) => [key, value])) // {}
// 只有一個鍵值對
console.log(mapEntries({ key: 'value' }, (key, value) => [key.toUpperCase(), value]))
// { KEY: 'value' }
// 包含空值
console.log(mapEntries({ a: 1, b: null, c: undefined }, (key, value) => [
key,
value ?? 'default'
]))
// { a: 1, b: 'default', c: 'default' }
處理復雜映射場景
typescript
import { mapEntries } from 'radash'
const complexObj = {
user: {
profile: {
name: 'Alice',
age: 25
},
settings: {
theme: 'dark',
language: 'en'
}
},
system: {
version: '1.0.0',
environment: 'production'
}
}
// 深度扁平化復雜對象
const mapped = mapEntries(complexObj, (key, value) => {
const flatten = (obj: any, prefix = ''): [string, any][] => {
return Object.entries(obj).flatMap(([k, v]) => {
const newKey = prefix ? `${prefix}_${k}` : k
if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
return flatten(v, newKey)
}
return [[newKey, v]]
})
}
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
return flatten(value, key)
}
return [key, value]
})
console.log(mapped)
// {
// user_profile_name: 'Alice',
// user_profile_age: 25,
// user_settings_theme: 'dark',
// user_settings_language: 'en',
// system_version: '1.0.0',
// system_environment: 'production'
// }
注意事項
- 映射函數: 映射函數必須返回
[string, any]
格式的數組 - 嵌套對象: 需要手動處理嵌套對象的映射
- 數組值: 數組值會保持原樣,需要特殊處理
- 不可變性: 返回新對象,不修改原對象
- 類型安全: 支持TypeScript類型推斷
與其他方法的區別
Object.entries()
: 獲取鍵值對數組mapEntries()
: 映射鍵值對並返回新對象mapKeys()
: 只映射鍵名mapValues()
: 只映射值
實際應用場景
- 數據轉換: 在不同系統間轉換數據格式
- API適配: 適配不同API的數據格式
- 配置處理: 處理配置對象的結構轉換
- 日志格式化: 格式化日志數據的結構
- 數據庫映射: 映射數據庫字段名和值