【问题标题】:Is there a way to refactor this AND and XOR logical branch?有没有办法重构这个 AND 和 XOR 逻辑分支?
【发布时间】:2020-06-24 20:14:27
【问题描述】:

我有 2 个用户 ID,如果我只有一个或两个,我想做不同但非常相似的逻辑。有没有办法整合这段代码,因为现在看起来很难看。


function getUserPermission(primaryId, secondaryId, role) {
  let permission = userInfo.permissionList.filter( permission => {

    //logical AND
    if(primaryId && secondaryId){
      // have both IDs, use both IDs
      (permission.primaryId === primaryId && permission.secondaryId === secondaryId) && permission.role === role
    } 

    //logical XOR
    else if((primaryId && !secondaryId) || (!primaryId && secondaryId)) {
      // have only 1 ID, use 1 ID 
      (permission.primaryId === primaryId || permission.secondaryId === secondaryId) && permission.role === role
    }

  })[0]

  return permission
}

【问题讨论】:

    标签: javascript logical-operators boolean-logic boolean-operations


    【解决方案1】:

    首先,当两个 id 都无效时,这个逻辑似乎无法处理。你会想以某种方式处理这个问题(到目前为止,看起来其他两个答案都包括这些方面的内容)。

    接下来,由于您只返回第一个匹配权限,我建议您使用一种在找到第一个匹配项后不会继续循环的解决方案。在这方面,Array.find() 在这个用例中比 Array.filter() 好得多。

    如果我把其他答案放在一起,会是这样的:

    function getUserPermission(primaryId, secondaryId, role) {
      if (!primaryId && !secondaryId) return null // at least one must be populated, why loop at all?
      return userInfo.permissionList.find(permission => 
        permission.role === role
          && (!primaryId || primaryId === permission.primaryId) // if primary is populated, it needs to match
          && (!secondaryId || secondaryId === permission.secondaryId) // if secondary is populated, it needs to match
      );
    }
    

    ...但这不能处理完全有效的 ID 恰好为 0 的情况。不过,这可能取决于您的数据。例如,也许您总是使用基于字符串的 ID。它还会检查每个循环上的有效 ID(您可能会或可能不会完全满意)

    考虑到这些潜在问题,我对您的数据/类型做了一些假设,并提出了一种更非正统的方法来尝试解决它们:

    const getUserPermission = (primaryId = -1, secondaryId = -1, role = '') => {
      if (primaryId < 0 && secondaryId < 0) return null
    
      const conditions = [ p => p.role === role ]
        .concat(primaryId >= 0 ? [ p => p.primaryId === primaryId ] : [])
        .concat(secondaryId >= 0 ? [ p => p.secondaryId === secondaryId ] : [])
    
      return userInfo.permissionList.find(p => conditions.every(fn => fn(p)))
    }
    

    ...最后一个函数创建了一个函数数组conditions,用于检查每个权限。应该返回匹配每个条件的第一个(理论上,至少 - 我没有测试它)

    【讨论】:

    • 感谢您的详尽解释。数据为字符串格式(包含 6 个字符),因此不需要您的替代解决方案。但是,跳出框框思考是值得称赞的!
    【解决方案2】:

    这样的事情呢?

    if(!primaryId && !secondaryId) {
      throw Error("No ID was provided");
    }
    let permission = userInfo.permissionList.filter(p => p.role === role);
    if(primaryId) {
      permission = permission.filter(p => p.primaryId === primaryId);
    }
    if(secondaryId) {
      permission = permission.filter(p => p.secondaryId === secondaryId);
    }
    return permission[0];
    

    【讨论】:

      【解决方案3】:
      function getUserPermission(primaryId, secondaryId, role) {
        return userInfo.permissionList.find(permission => 
          permission.role === role
            && (!!primaryId || !!secondaryId)// at least one is populated
            && (!primaryId || primaryId === permission.primaryId)// if primary is populated, it needs to match
            && (!secondaryId || secondaryId === permission.secondaryId)// if secondary is populated, it needs to match
          );
      }
      

      这与您的代码略有不同,如果没有匹配,则返回 null,而您的则抛出异常。如果你想抛出,你总是可以把结果放在一个变量中并检查是否为空。

      【讨论】:

        【解决方案4】:

        这次重构怎么样:

        function getUserPermission(primaryId = undefined,secondaryId = undefined,role) {
        
          primaryId === undefined && secondaryId === undefined && throw new Error("Ids are required");
        
          const userPermission = userInfo.permissionList
            .filter((permission) => role && permission.role === role)
            .filter((permission) => primaryId && permission.primaryId === primaryId)
            .filter(
              (permission) => secondaryId && permission.secondaryId === secondaryId
            );
        
          return userPermission[0];
        }
        

        【讨论】:

          猜你喜欢
          • 2018-05-04
          • 1970-01-01
          • 2018-10-14
          • 1970-01-01
          • 1970-01-01
          • 2021-11-15
          • 1970-01-01
          • 2020-06-26
          • 1970-01-01
          相关资源
          最近更新 更多