Javascript Filter返回两个对象

时间:2016-09-17 19:52:27

标签: javascript ecmascript-6 redux

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;
  }
}

1 个答案:

答案 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;
&#13;
&#13;

但更好的方法是在预期的每个地方真正归还布尔值。因此C应该只返回条件的结果,而B可以使用some而不是filter,这不仅会返回一个布尔值,而且还会停止进一步查看找到匹配。在A中,您现在可以拥有原始代码,因为您真的希望A返回数据(而不是布尔值)。

另请注意,您可以对仅包含已评估表达式的箭头函数使用快捷符号:

&#13;
&#13;
  // 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;
&#13;
&#13;