将for循环转换为reduce



我以前写过一段代码,用另一种格式更改对象。更改对象如下:

{
"testType": {
"testCatType": {
"testSubCat": {
"testSubSubCat1": {},
"testSubSubCat2": {}
}
}
},
"newType": {
"newCat10": {
"newCatSub1": {
"bingo11": {},
"bingo12": {},
"bingo15": {}
}
}
},
"displacement": {},
....
}

通过我的代码,我将其更改为以下格式:

[
{
"label": "testType",
"categories": [
{
"label": "testCatType",
"subCategories": [
{
"label": "testSubCat",
"subSubCategories": [
{
"label": "testSubSubCat1"
},
{
"label": "testSubSubCat2"
}
]
}
]
}
]
},
{
"label": "newType",
"categories": [
{
"label": "newCat10",
"subCategories": [
{
"label": "newCatSub1",
"subSubCategories": [
{
"label": "bingo11"
},
{
"label": "bingo12"
},
{
"label": "bingo15"
}
]
}
]
}
]
},
{
"label": "displacement",
"categories": []
},
{
"label": "imperfection",
"categories": [
{
"label": "metal",
"subCategories": [
{
"label": "clean",
"subSubCategories": []
},
{
"label": "scratched",
"subSubCategories": []
}
]
},
{
"label": "dust",
"subCategories": []
},
{
"label": "leakage",
"subCategories": []
},
{
"label": "wipe mark",
"subCategories": []
},
{
"label": "fingerprint",
"subCategories": []
},
{
"label": "grunge",
"subCategories": []
},
{
"label": "other",
"subCategories": []
},
{
"label": "rubber",
"subCategories": []
},
{
"label": "grain",
"subCategories": []
},
{
"label": "stone",
"subCategories": []
},
{
"label": "stain",
"subCategories": []
}
]
},
{
"label": "surface",
"categories": [
{
"label": "metal",
"subCategories": [
{
"label": "bare",
"subSubCategories": []
},
{
"label": "corroded",
"subSubCategories": []
},
{
"label": "corrugated",
"subSubCategories": []
},
{
"label": "gun",
"subSubCategories": []
},
{
"label": "painted",
"subSubCategories": []
},
{
"label": "sheet",
"subSubCategories": []
},
{
"label": "treated",
"subSubCategories": []
}
]
},
{
"label": "wood",
"subCategories": [
{
"label": "board",
"subSubCategories": []
},
{
"label": "log",
"subSubCategories": []
},
{
"label": "other",
"subSubCategories": []
},
{
"label": "parquet",
"subSubCategories": []
},
{
"label": "plank",
"subSubCategories": []
},
{
"label": "veneer",
"subSubCategories": []
}
]
},
{
"label": "fabric",
"subCategories": [
{
"label": "carpet",
"subSubCategories": []
},
{
"label": "leather",
"subSubCategories": []
},
{
"label": "pattern",
"subSubCategories": []
},
{
"label": "plain",
"subSubCategories": []
}
]
},
{
"label": "grass",
"subCategories": [
{
"label": "artificial",
"subSubCategories": []
},
{
"label": "dried",
"subSubCategories": []
},
{
"label": "lawn",
"subSubCategories": []
},
{
"label": "patchy",
"subSubCategories": []
},
{
"label": "wild",
"subSubCategories": []
}
]
},
{
"label": "concrete",
"subCategories": [
{
"label": "cast in situ",
"subSubCategories": []
},
{
"label": "damaged",
"subSubCategories": []
},
{
"label": "dirty",
"subSubCategories": []
},
{
"label": "painted",
"subSubCategories": []
},
{
"label": "rough",
"subSubCategories": []
},
{
"label": "slab",
"subSubCategories": []
},
{
"label": "smooth",
"subSubCategories": []
}
]
},
{
"label": "sand",
"subCategories": [
{
"label": "beach",
"subSubCategories": []
},
{
"label": "desert",
"subSubCategories": []
}
]
},
{
"label": "stone",
"subCategories": [
{
"label": "castle",
"subSubCategories": []
},
{
"label": "cobblestone",
"subSubCategories": []
},
{
"label": "floor",
"subSubCategories": []
},
{
"label": "mosaic",
"subSubCategories": []
},
{
"label": "terrazzo",
"subSubCategories": []
},
{
"label": "wall",
"subSubCategories": []
}
]
},
{
"label": "plaster",
"subCategories": [
{
"label": "damaged",
"subSubCategories": []
},
{
"label": "fresh",
"subSubCategories": []
},
{
"label": "old",
"subSubCategories": []
},
{
"label": "painted",
"subSubCategories": []
}
]
},
{
"label": "soil",
"subCategories": [
{
"label": "clay",
"subSubCategories": []
},
{
"label": "mud",
"subSubCategories": []
},
{
"label": "mulch",
"subSubCategories": []
},
{
"label": "sandy",
"subSubCategories": []
}
]
},
{
"label": "rock",
"subCategories": [
{
"label": "cliff",
"subSubCategories": []
},
{
"label": "granite",
"subSubCategories": []
},
{
"label": "jagged",
"subSubCategories": []
},
{
"label": "lava",
"subSubCategories": []
},
{
"label": "mossy",
"subSubCategories": []
},
{
"label": "rough",
"subSubCategories": []
},
{
"label": "smooth",
"subSubCategories": []
}
]
},
{
"label": "moss",
"subCategories": [
{
"label": "ground",
"subSubCategories": []
},
{
"label": "rock",
"subSubCategories": []
}
]
},
{
"label": "debris",
"subCategories": [
{
"label": "construction",
"subSubCategories": []
},
{
"label": "nature",
"subSubCategories": []
}
]
},
{
"label": "brick",
"subCategories": [
{
"label": "modern",
"subSubCategories": []
},
{
"label": "mortar",
"subSubCategories": []
},
{
"label": "painted",
"subSubCategories": []
},
{
"label": "rough",
"subSubCategories": []
}
]
},
{
"label": "tile",
"subCategories": [
{
"label": "ceramic",
"subSubCategories": []
},
{
"label": "grout",
"subSubCategories": []
},
{
"label": "pavestone",
"subSubCategories": []
},
{
"label": "sidewalk",
"subSubCategories": []
}
]
},
{
"label": "asphalt",
"subCategories": [
{
"label": "fine",
"subSubCategories": []
},
{
"label": "rough",
"subSubCategories": []
},
{
"label": "torn",
"subSubCategories": []
}
]
},
{
"label": "other",
"subCategories": [
{
"label": "climber",
"subSubCategories": []
},
{
"label": "creature",
"subSubCategories": []
},
{
"label": "dirt road",
"subSubCategories": []
},
{
"label": "edible",
"subSubCategories": []
},
{
"label": "fur",
"subSubCategories": []
},
{
"label": "paper",
"subSubCategories": []
},
{
"label": "various",
"subSubCategories": []
}
]
},
{
"label": "snow",
"subCategories": [
{
"label": "mixed",
"subSubCategories": []
},
{
"label": "pure",
"subSubCategories": []
}
]
},
{
"label": "bark",
"subCategories": [
{
"label": "beech",
"subSubCategories": []
},
{
"label": "birch",
"subSubCategories": []
},
{
"label": "oak",
"subSubCategories": []
},
{
"label": "other",
"subSubCategories": []
},
{
"label": "palm",
"subSubCategories": []
},
{
"label": "pine",
"subSubCategories": []
},
{
"label": "willow",
"subSubCategories": []
}
]
},
{
"label": "gravel",
"subCategories": [
{
"label": "construction",
"subSubCategories": []
},
{
"label": "natural",
"subSubCategories": []
},
{
"label": "pebbledash",
"subSubCategories": []
}
]
},
{
"label": "marble",
"subCategories": [
{
"label": "polished",
"subSubCategories": []
},
{
"label": "rough",
"subSubCategories": []
},
{
"label": "tile",
"subSubCategories": []
}
]
},
{
"label": "ground",
"subCategories": [
{
"label": "forest",
"subSubCategories": []
},
{
"label": "jungle",
"subSubCategories": []
},
{
"label": "other",
"subSubCategories": []
},
{
"label": "roots",
"subSubCategories": []
}
]
},
{
"label": "roofing",
"subCategories": [
{
"label": "new",
"subSubCategories": []
},
{
"label": "old",
"subSubCategories": []
}
]
},
{
"label": "antique",
"subCategories": [
{
"label": "asian",
"subSubCategories": []
},
{
"label": "medieval",
"subSubCategories": []
},
{
"label": "middle-eastern",
"subSubCategories": []
},
{
"label": "roman",
"subSubCategories": []
}
]
},
{
"label": "coal",
"subCategories": [
{
"label": "brick",
"subSubCategories": []
},
{
"label": "debris",
"subSubCategories": []
}
]
}
]
},
{
"label": "brush",
"categories": [
{
"label": "blood",
"subCategories": []
},
{
"label": "damage",
"subCategories": []
},
{
"label": "grunge",
"subCategories": []
},
{
"label": "leakage",
"subCategories": []
},
{
"label": "print",
"subCategories": []
},
{
"label": "spatter",
"subCategories": []
},
{
"label": "sponge",
"subCategories": []
},
{
"label": "spray",
"subCategories": []
},
{
"label": "stain",
"subCategories": []
},
{
"label": "traditional",
"subCategories": []
}
]
}
]

我写的一段想要优化的代码如下:

let typesObj = [];
for (let type in categoryTreeV3) {
let typeObj = {
label: type,
categories: []
};
for (let cat in categoryTreeV3[type]) {
let categoryObj = {
label: cat,
subCategories: []
};
for (var subCat in categoryTreeV3[type][cat]) {
if (typeof categoryTreeV3[type][cat][subCat] === "object") {
categoryObj.subCategories.push({
label: subCat,
subSubCategories: _.map(_.keys(categoryTreeV3[type][cat][subCat]), value => ({ "label": value }))
});
}
}
typeObj.categories.push(categoryObj);
}
typesObj.push(typeObj)
}
console.log(typesObj);

现在我一直在使用reduce((、map((和filter((方法,但容量有限,但不特别了解如何使用它进行优化。我将在下面粘贴我的尝试:

let test = [];
let b = [];
_.reduce(categoryTreeV3, (index, cats, key) => {
return test.push({
label: key,
categories: _.reduce(cats, (i, subCat, k) => {
b = b.concat({
label: k,
subCategories: subCat
});
return b;
}, b)
})
}, test);

但这并没有给我预期的结果。此外,它再次将我带向嵌套,这是我最初想要避免的,以便我的代码可读。有人能在这方面帮助我吗。

您可以通过使用数据构造函数和使用它的递归函数来极大地简化您的逻辑:

const childrenName = level =>
`${"Sub".repeat(level)}Category`.replace(/^./, c => c.toLowerCase());
const Category = level => (label, next) => {
const obj = { label };
const children = transform(next, Category(level + 1));

if (children.length > 0)
obj[childrenName(level)] = children;
return obj;
};
const transform = (obj, dataConstructor = Category(0)) =>
Object.entries(obj)
.map(([key, value]) => dataConstructor(key, value));
const input = {
"testType": {
"testCatType": {
"testSubCat": {
"testSubSubCat1": {},
"testSubSubCat2": {}
}
}
},
"newType": {
"newCat10": {
"newCatSub1": {
"bingo11": {},
"bingo12": {},
"bingo15": {}
}
}
},
"displacement": {},
}
console.log(transform(input));
.as-console-wrapper {
max-height: 100% !important;
}

对于顶级,将使用默认的MainCategory,因此其子级将位于categories之下。每降一级,孩子们就多降一级;sub"+"类别`。

与其考虑reduce,不如用一个相当简单的递归来处理:

const decap = ([s, ...ss]) =>
s .toLowerCase () + ss .join ('')
const convert = (obj, depth = 0) => 
Object.entries (obj) .map (([k, v]) => ({
label: k, 
...(Object .keys (v) .length > 0 
? {[decap (`${'Sub' .repeat (depth) }Categories`)]: convert(v, depth + 1)} 
: {}
)
}))
const input = {testType: {testCatType: {testSubCat: {testSubSubCat1: {}, testSubSubCat2: {}}}}, newType: {newCat10: {newCatSub1: {bingo11: {}, bingo12: {}, bingo15: {}}}}, displacement: {}}
console .log (convert (input))
.as-console-wrapper {max-height: 100% !important; top: 0}

我们从助手decap开始,它只是将字符串的第一个字母小写,允许我们将"Categories""SubCategories""SubSubCategories"等更改为"categories""subCategories""subSubCategories"等。

主函数convert使用属性名称作为值,为输入中的每个条目添加一个label属性。如果原始值是一个非空对象,我们递归调用convert来创建其子对象,使用depth参数来跟踪当前级别需要为Categories准备多少个Sub前缀。然后我们将结果传递给CCD_ 17。

最新更新