[英]reduce es6 missing nested array of object using spread
我遇到了根据条件合并2组数据的问题。 我调试了一个多小时,但无法弄清楚原因。 我在下面创建了一个示例。
我有这两个数据:
const staticRockData = {
rockTypes: [
{
supplierRockTypes: [
{
rockCodes: ["1"],
match_id: "abc"
},
{
rockCodes: ["2"],
match_id: "abc"
}
]
}
]
};
const gatewayRockData = {
match_id: "abc",
rocks: [{ rock_type: "1", rates: [] }, { rock_type: "2", rates: [] }]
};
我有这个映射逻辑:
let rockTypes = staticRockData.rockTypes;
rockTypes = rockTypes.reduce((accum, rockType) => {
const matchedSourceId = rockType.supplierRockTypes.some(
o2 => o2.match_id === gatewayRockData.match_id
);
if (matchedSourceId) {
gatewayRockData.rocks.forEach(rock => {
const matchRockType = rockType.supplierRockTypes.some(o2 => {
return o2.rockCodes.includes(rock.rock_type);
});
if (matchRockType) {
console.log("rock.rock_type", rock.rock_type);
rockType = {
...rockType,
rock_type: rock.rock_type,
rates: rock.rates
};
}
});
}
accum = [...accum, { ...omit(rockType, "supplierRockTypes") }];
return accum;
}, []);
return {
rocks: rockTypes
};
我期待这个:
rocks: [
{
rates: [],
rock_type: "1"
},
{
rates: [],
rock_type: "2"
}
]
}
目前的解决方案缺少这个:
{ rates: [], rock_type: "1"}
,我想知道我的错误在哪里。
忽略是lodash的omit
功能,但我认为这不是罪魁祸首。 我在这里创建了一个演示:
https://codesandbox.io/s/condescending-platform-1jp9l?fontsize=14&previewwindow=tests
每次重复循环时都会覆盖rockType:
rockType = {
...rockType,
rock_type: rock.rock_type,
rates: rock.rates
};
您应该以这种方式将结果存储在另一个变量中:
...
let matchedRockTypes = [];
if (matchedSourceId) {
gatewayRockData.rocks.forEach(rock => {
const matchRockType = rockType.supplierRockTypes.some(o2 => {
return o2.rockCodes.includes(rock.rock_type);
});
if (matchRockType) {
console.log("rock.rock_type", rock.rock_type);
matchedRockTypes.push({
rock_type: rock.rock_type,
rates: rock.rates
});
}
});
}
return matchedRockTypes;
...
我不知道你的具体要求,但我发现导致问题的原因问题出在你的reducer的forEach中,这个问题在下面的版本中得到修复:
rockTypes = rockTypes.reduce((accum, rockType) => {
const matchedSourceId = rockType.supplierRockTypes.some(
o2 => o2.match_id === gatewayRockData.match_id
);
if (matchedSourceId) {
gatewayRockData.rocks.forEach(rock => {
const matchRockType = rockType.supplierRockTypes.some(o2 => {
return o2.rockCodes.includes(rock.rock_type);
});
if (matchRockType) {
accum = [...accum, { rock_type: rock.rock_type,
rates: rock.rates }];;
}
});
}
return accum;
}, []);
更具体地说,在forEach下面的行:
if (matchRockType) {
rockType = {
...rockType,
rock_type: rock.rock_type,
rates: rock.rates
};
}
每次循环运行并且找到匹配的时候它会替换你的rockType内容,因为它是一个对象而不是一个数组。
其他解决方案在forEach外部获取一个空数组,并在内部推送内容if条件并在返回时传播它。
只是说你应该考虑重构你的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.