对象,值作为键,使用reduce:Javascript存储与其相关的每个单独对象



正在处理一个问题,想知道是否有人能对我遇到的这个问题有所了解。我应该获取一个对象数组(一组park(,我需要从嵌套在其中的对象中获取一个键,将其用作新键,并存储与我们为该键提取的相同值相关的每个对象的数组。这里有一个例子:

我使用的数据看起来很像:

const myParks = [
{
name: "Garden of the Gods",
areaInSquareKm: 200,
location: {
state: "Colorado"
}
},
{
name: "Acadia",
areaInSquareKm: 198.6,
location: {
state: "Maine"
}
},
{
name: "Mountain Pass",
areaInSquareKm: 400.6,
location: {
state: "Colorado"
}
},
{
name: "Newleaf Forest",
areaInSquareKm: 150.4,
location: {
state: "Maine"
}
},
];

我需要取location.state值,并将其用作新对象的单独键,然后为每个键分配一个具有相关状态的对象值。如果状态是Maine,则密钥应包含具有相关状态的整个对象:

{
"Maine": [
{
name: "Acadia",
areaInSquareKm: 198.6,
location: {
state: "Maine"
}
},
{
name: "Newleaf Forest",
areaInSquareKm: 150.4,
location: {
state: "Maine"
}
},
]
};

我试着这样做:

function parkByState(parks) {
let stateParks = parks.reduce((result, park) => {
result[park.location.state] = parks.filter(park => { park.location.state })
}, {});
return stateParks
};

我一辈子都想不出该怎么做。我不能更改结构,它们必须组装在一个对象中,以状态名称作为关键字,并且如果状态与关键字匹配,则有一个包含每个单独公园的数组。我真的不知道自己做错了什么。我一直收到一个错误:

Uncaught TypeError: Cannot set properties of undefined (setting 'Maine')
at <anonymous>:37:35
at Array.reduce (<anonymous>)
at parkByState (<anonymous>:36:26)
at <anonymous>:42:18

我对JavaScript还比较陌生,如果有人能对此有所了解,我会很高兴。我需要使用reduce((方法来组装对象。我认为使用filter将对象过滤到每个键中是有意义的,但我似乎无法使这两种方法正确地协同工作。你不必告诉我答案,但至少,请告诉我我在这里做错了什么。我试过几种不同的方法来做到这一点,但似乎都不起作用。如果我错过了如何使用这些方法的关键点,请让我知道我能做些什么来更好地理解他们试图做什么。我真的很感激所有的帮助,如果这是一个愚蠢的问题,我道歉。我只是想了解如何重新组装每个公园的阵列,存储在从每个公园的状态中提取的密钥中。如果这个问题的措辞不是最好的,我很抱歉,我真的想在这方面做得更好,所以我只是想了解我在这里做错了什么,以及我如何才能达到预期的结果。

提前谢谢。

没有reduce,我们可以做:

const myParks = [
{
name: "Garden of the Gods",
areaInSquareKm: 200,
location: {
state: "Colorado"
}
},
{
name: "Acadia",
areaInSquareKm: 198.6,
location: {
state: "Maine"
}
},
{
name: "Mountain Pass",
areaInSquareKm: 400.6,
location: {
state: "Colorado"
}
},
{
name: "Newleaf Forest",
areaInSquareKm: 150.4,
location: {
state: "Maine"
}
},
];
const stateNames = new Set(myParks.map(area => {
return area.location.state;
}));
const collectionsByStateName = {};
[...stateNames].forEach(stateName => {
collectionsByStateName[stateName] = [];
myParks.forEach(area => {
if(stateName === area.location.state) {
collectionsByStateName[stateName].push(area);
}
})
});
console.log(collectionsByStateName);

传递给.reduce()的回调应该返回一个值。当你给一个箭头函数一个主体{}时,如果你想从它返回一个值,它必须包括return,否则,它将返回undefined。因为您没有从reduce回调返回任何内容,所以它当前返回undefined,所以在下一次迭代中,result将是undefined。当你试图设置undefind的值时,这会导致你的错误,但你不能这样做。此外,当你想保留这个值时,你的.filter()需要返回一个真实的值,而当你想放弃它时,你需要返回一一个虚假的值。

虽然您可以对代码进行一些修改以使过滤器工作,但我建议您不要进行任何过滤。相反,检查当前公园的当前状态,如果该状态已经在result中,则推送到现有阵列,否则,使用保持当前状态的新阵列为该状态创建一个新的密钥输入结果:

const myParks = [ { name: "Garden of the Gods", areaInSquareKm: 200, location: { state: "Colorado" } }, { name: "Acadia", areaInSquareKm: 198.6, location: { state: "Maine" } }, { name: "Mountain Pass", areaInSquareKm: 400.6, location: { state: "Colorado" } }, { name: "Newleaf Forest", areaInSquareKm: 150.4, location: { state: "Maine" } }, ];
function parkByState(parks) {
let stateParks = parks.reduce((result, park) => {
const key = park.location.state;
result[key] ??= []; // set `key` to an empty array if it doesn't exist, (similar to result[key] = result[key] || [];)
result[key].push(park);
return result;
}, {});
return stateParks;
};
console.log(parkByState(myParks));

正如你所说的,你是JavaScript的新手,但我会在这里取消.reduce()。这个特殊的例子实际上不需要使用.reudce(),并且可以通过使用for循环来提高可读性。我还用if语句替换了nullish合并运算符,如果您不熟悉??,该语句可能会准备得更清楚

function parkByState(parks) {
const stateParks = {};
for(const park of parks) {
const key = park.location.state;
if(!stateParks[key])
stateParks[key] = [];
stateParks[key].push(park);
}
return stateParks;
}

最新更新