我想做類似以下的事情,但以更大規模和更有效的方式。假設我有一個物件陣列,其中每個物件都需要水平/展平。
轉換這樣的東西......
[{
name: 'John Doe',
address: {
apartment: 1550,
streetno: 167,
streetname: 'Victoria',
},
}, {
name: 'Joe Smith',
address: {
apartment: 2,
streetno: 111,
streetname: 'Jones',
},
}]
……到那個……
[{
name: 'John Doe',
apartment: 1550,
streetno: 167,
streetname: 'Victoria',
}, {
name: 'Joe Smith',
apartment: 2,
streetno: 111,
streetname: 'Jones',
}]
如上所示,address還有一個需要調平/展平的物件。
但最重要的是,人們事先并不知道物件/資料結構。因此,人們既不知道屬性名稱也不知道嵌套級別的深度。
uj5u.com熱心網友回復:
“所以在收到這個物體之前,你對它的結構知之甚少。”
OP 的主要任務實際上是將任何給定的基于嵌套物件的資料結構平級為僅具有單個條目級別的物件。而且由于人們事先對資料結構一無所知,因此必須提出一種遞回方法。
一旦實作,這種原因函式可以用作陣列mapping 程序的回呼。
遞回實作本身是基于型別檢測(區分Array- 和 -Object型別和原始值)和根據當前處理的型別的物件reduce的entries(鍵值對) 。value
function recursivelyLevelObjectEntriesOnly(type) {
let result = type;
if (Array.isArray(type)) {
result = type
.map(recursivelyLevelObjectEntriesOnly);
} else if (type && 'object' === typeof type) {
result = Object
.entries(type)
.reduce((merger, [key, value]) => {
if (value && 'object' === typeof value && !Array.isArray(value)) {
Object.assign(merger, recursivelyLevelObjectEntriesOnly(value));
} else {
merger[key] = recursivelyLevelObjectEntriesOnly(value);
}
return merger;
}, {});
}
return result;
}
const sampleData = [{
name: 'John Doe',
address: { apartment: 1550, streetno: 167, streetname: 'Victoria' },
}, {
name: 'Joe Smith',
address: { apartment: 2, streetno: 111, streetname: 'Jones' },
}, {
foo: {
bar: "bar",
baz: "baz",
biz: {
buzz: "buzz",
bizz: [{
name: 'John Doe',
address: { apartment: 1550, streetno: 167, streetname: 'Victoria' },
}, {
name: 'Joe Smith',
address: { apartment: 2, streetno: 111, streetname: 'Jones' },
}, {
foo: {
bar: "bar",
baz: "baz",
biz: {
buzz: "buzz",
booz: {
foo: "foo",
},
},
},
}],
booz: {
foo: "foo",
},
},
},
}];
const leveledObjectData = sampleData.map(recursivelyLevelObjectEntriesOnly);
console.log({ leveledObjectData });
// no mutation at `sampleData`.
console.log({ sampleData });
.as-console-wrapper { min-height: 100%!important; top: 0; }
uj5u.com熱心網友回復:
假設您有這些物件的陣列,您可以使用解構輕松地將每個物件與其“地??址”屬性結合起來:
const myInput = [
{
name: 'john doe',
address: { apartment: 1550, streetno: 167, streetname: 'Victoria'}
},
{
name: 'Joe Smith',
address: { apartment: 2, streetno: 111, streetname: 'Jones'}
}
];
const myOutput = myInput.map(({address, ...rest}) => ({...rest, ...address}));
console.log(myOutput);
uj5u.com熱心網友回復:
map遍歷陣列并回傳一個已將其address屬性合并到其中的新物件,洗掉地址屬性,并回傳新物件。
const arr=[{name:"john doe",address:{apartment:1550,streetno:167,streetname:"Victoria",a:"a"},b:"b"}];
const out = arr.map(obj => {
const newObj = { ...obj, ...obj.address };
delete newObj.address;
return newObj;
});
console.log(out);
uj5u.com熱心網友回復:
這是一種基于遞回函式的相當簡單的方法,它首先將元素轉換為以下形式,然后呼叫Object .fromEntries結果:
[
["name", "John Doe"],
["apartment", 1550],
["streetno", 167],
["streetname", "Victoria"]
]
它看起來像這樣:
const deepEntries = (o) =>
Object .entries (o) .flatMap (([k, v]) => v.constructor === Object ? deepEntries (v) : [[k, v]])
const deepFlat = (o) =>
Object .fromEntries (deepEntries (o))
const deepFlatAll = (xs) =>
xs .map (deepFlat)
const input = [{name: 'John Doe', address: {apartment: 1550, streetno: 167, streetname: 'Victoria'}, }, {name: 'Joe Smith', address: {apartment: 2, streetno: 111, streetname: 'Jones'}}]
console .log (deepFlatAll (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
但是您確實有一個可能的重大問題。如果您要扁平化多個級別,則不同級別很可能具有相同名稱的節點;當您將物件重新組合在一起時,其中大部分都會被破壞。
解決此類問題的一種方法是展平為不同的格式。我已經看到這樣的東西非常成功地使用:
{
"name": "John Doe",
"address.apartment": 1550,
"address.streetno": 167,
"address.streetname": "Victoria"
}
如果您環顧 StackOverflow,您當然可以找到如何做到這一點的答案。
uj5u.com熱心網友回復:
那不是陣列。
如果要展平字典,請這樣做:https ://stackoverflow.com/a/22047469/5676613
這具有 O(n^k) 和 Omega(n) 時間復雜度,其中 n 是字典的大小,k 是字典的深度(或字典中有多少個嵌套)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/482923.html
標籤:javascript 递归 数据结构 映射 减少
