ERS, 我对这个算法有些麻烦。
我正在使用Redux,但我认为这与此问题无关。基本上,此代码中的console.log语句只返回一个对象,但是函数A返回两个对象的数组(即使是未在函数C中通过测试的对象)
我将这些功能分成3部分,看看是否有助于我解决这个问题,但我还是无法解决这个问题。
有什么建议吗?
const A = (state) => {
// looks through an array and passes down a resource
return state.resources.locked.filter((resource) => {
return B(state, resource);
})
};
// looks through an array and passes down a building
const B = (state, resource) => {
return state.bonfire.allStructures.filter((building) => {
return C(building, resource);
})
};
// checks if building name and resource requirment are the same, and if building is unlocked
// then returns only that one
const C = (building, resource) => {
if (building.unlocked && building.name == resource.requires.structure) {
console.log(resource);
return resource;
}
}
答案 0 :(得分:1)
使用filter
时,请注意要传递给它的回调函数应该返回一个布尔值,指示是否需要过滤特定元素。
但在你的情况下,B
不返回布尔值,而是返回数组。即使该数组为空(表示没有资源匹配),filter
也不会将此值视为false,因此相应的资源仍会出现在A
返回的数组中。
快速修复:获取B
返回的数组的长度,然后返回该数组。零将被视为错误:
const A = (state) => {
// looks through an array and passes down a resource
return state.resources.locked.filter((resource) => {
return B(state, resource).length; /// <---- length!
})
};
// looks through an array and passes down a building
const B = (state, resource) => {
return state.bonfire.allStructures.filter((building) => {
return C(building, resource);
})
};
// checks if building name and resource requirement are the same, and if building
// is unlocked and then returns only that one
const C = (building, resource) => {
if (building.unlocked && building.name == resource.requires.structure) {
return resource;
}
}
// Sample data. Only x matches.
var state = {
resources: {
locked: [{ // resource
requires: {
structure: 'x'
}
}, { // resource
requires: {
structure: 'y'
}
}]
},
bonfire: {
allStructures: [{ // building
unlocked: true,
name: 'x'
}, { // building
unlocked: true,
name: 'z'
}]
}
};
console.log(A(state));
&#13;
但更好的方法是在预期的每个地方真正归还布尔值。因此C
应该只返回条件的结果,而B
可以使用some
而不是filter
,这不仅会返回一个布尔值,而且还会停止进一步查看找到匹配。在A
中,您现在可以拥有原始代码,因为您真的希望A
返回数据(而不是布尔值)。
另请注意,您可以对仅包含已评估表达式的箭头函数使用快捷符号:
// looks through an array and passes down a resource
const A = state => state.resources.locked.filter( resource => B(state, resource) );
// looks through an array and passes down a building
// Use .some instead of .filter: it returns a boolean
const B = (state, resource) =>
state.bonfire.allStructures.some( building => C(building, resource) );
// checks if building name and resource requirment are the same, and if building
// is unlocked and then returns only that one
// Return boolean
const C = (building, resource) => building.unlocked
&& building.name == resource.requires.structure;
// Sample data. Only x matches.
var state = {
resources: {
locked: [{ // resource
requires: {
structure: 'x'
}
}, { // resource
requires: {
structure: 'y'
}
}]
},
bonfire: {
allStructures: [{ // building
unlocked: true,
name: 'x'
}, { // building
unlocked: true,
name: 'z'
}]
}
};
console.log(A(state));
&#13;