【问题标题】:Formatting the filter function inside array with if else condition使用 if else 条件格式化数组内的过滤器函数
【发布时间】:2019-09-10 19:19:53
【问题描述】:

在下面的代码中有 usersData 对象,其中包含 usersList 数组。

const usersData = {
  usersList: [
    {
      user: "user1",
      langSpeak: ["IND","SPN"],
    },
    {
      
      user: "user2",
      langSpeak: ["IND"],
    },
    {
     
      user: "user1",
      langSpeak: ["IND", "SPN", "JPN"],
    },
    {
     
      user: "user3",
      langSpeak: ["IND", "SPN"],
    },
    {
      user: "user3"
    }
  ]
};

let usersKey = ["user","langSpeak"];
let usersValue = ["user1","IND","SPN"];
 
 let userColl = usersData.usersList.filter(userObj => {
  
  return usersKey.forEach( usersKey => {
    if(Array.isArray(userObj[usersKey])){
      return userObj[usersKey] && usersValue.forEach(x => {
        console.log("x===" + usersKey)
        return userObj[usersKey].includes(x)
      });
    }
     if(!Array.isArray(userObj[usersKey])){
      console.log(usersKey)
      return usersValue.includes(userObj[usersKey]);
    } 
  
      
  });
});

console.log(userColl); 

usersKeyusersValue

过滤键和值的代码已经存在。

我检查了过滤器函数的值是否包含数组,这取决于返回的过滤器数据。

并且最终输出存储到userColl变量中。

目前我在输出中得到 null,但我期待 firstthird userList 对象;还有条件是我不想更改usersKeyusersValue

提前致谢。

【问题讨论】:

  • 请同时提供预期的 JSON 或输出
  • 预期输出:usersList: [ { user: "user1", langSpeak: ["IND","SPN"], }, { user: "user1", langSpeak: ["IND", " SPN", "JPN"], }]
  • usersKeyuserValue有什么用?
  • 而且,原始 JSON 中的任何地方都不存在关键的“代码”?
  • 不应该是usersKey["user", "langSpeak"]

标签: javascript arrays function object ecmascript-6


【解决方案1】:

您可以规范化您的约束并获取一个数组,因为它很容易与另一个键值数组和其他数组中的所需值进行迭代。

然后迭代constraints 并检查对象中的值是否为数组。根据此检查迭代值或进行单次检查。

var usersList = [{ user: "user1", langSpeak: ["IND", "SPN"] }, { user: "user2", langSpeak: ["IND"] }, { user: "user1", langSpeak: ["IND", "SPN", "JPN"] }, { user: "user3", langSpeak: ["IND", "SPN"] }, { user: "user3" }],
    constraints = [
        ["user", "user1"],
        ["langSpeak", "IND", "SPN"]
    ],
    result = usersList.filter(o => constraints.every(([key, ...values]) => Array.isArray(o[key])
        ? values.every(v => o[key].includes(v))
        : values.includes(o[key])    
    ));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    您可以使用filter 来过滤数组。使用every 检查是否所有元素都包含某个字符串。

    const usersData = {"usersList":[{"user":"user1","langSpeak":["IND","SPN"]},{"user":"user2","langSpeak":["IND"]},{"user":"user1","langSpeak":["IND","SPN","JPN"]},{"user":"user3","langSpeak":["IND","SPN"]},{"user":"user3"}]}
    
    let userFilter = "user1";                 //Assign a variable for filtering user
    let langFilter = ["IND", "SPN"];          //Assign a variable for filtering language
    
    let result = usersData.usersList.filter(o => o.user == userFilter && o.langSpeak && langFilter.every(e => o.langSpeak.includes(e)));
    
    let finalResult = {                       //Contruct the final object
      usersList: result
    }
    
    
    console.log(finalResult);

    如果你真的必须使用 usersKeyusersValue,你可以使用reduce 来总结过滤器,比如:

    const usersData = {"usersList":[{"user":"user1","langSpeak":["IND","SPN"]},{"user":"user2","langSpeak":["IND"]},{"user":"user1","langSpeak":["IND","SPN","JPN"]},{"user":"user3","langSpeak":["IND","SPN"]},{"user":"user3"}]}
    
    let usersKey = ["user", "langSpeak"];
    let usersValue = ["user1", "IND", "SPN"];
    
    let filter = usersKey.reduce((c, v, i, a) => {
      c[v] = i + 1 === a.length ? usersValue.slice(i) : [usersValue[i]];
      return c;
    }, {});
    
    
    let result = usersData.usersList.filter(o => Object.entries(filter).every(([k, v]) => v.every(x => o[k].includes(x))));
    
    let finalResult = {
      usersList: result
    }
    
    console.log(finalResult);

    【讨论】:

      【解决方案3】:

      您可以考虑将用作过滤器参数的变量更改为object,或者Map()

      请注意,在某些情况下,您使用变量的方法可能会出现问题,例如,如果某个用户被命名为 IND,会发生什么情况。您如何知道数组usersValue 的某些元素是否与过滤属性user 或属性langSpeak 相关?

      如果你使用一个对象,那么你可以这样进行:

      const usersData = {
        usersList: [
          {user: "user1", langSpeak: ["IND","SPN"]},
          {user: "user2", langSpeak: ["IND"]},
          {user: "user1", langSpeak: ["IND", "SPN", "JPN"]},
          {user: "user3", langSpeak: ["IND", "SPN"]},
          {user: "user3"}
        ]
      };
      
      let filterObj = {
        "user": ["user1"],
        "langSpeak": ["IND", "SPN"]
      };
      
      let userColl = usersData.usersList.filter(userObj =>
      {
          return Object.entries(filterObj).every(([k, v]) =>
          {
              let uVal = userObj[k];
      
              if (Array.isArray(uVal))
                  return v.every(x => uVal.includes(x));
              else
                  return v.includes(uVal);
          });
      });
      
      console.log(userColl);
      .as-console {background-color:black !important; color:lime;}
      .as-console-wrapper {max-height:100% !important; top:0;}

      【讨论】:

        【解决方案4】:

        您应该使用Array.every 来检查给定数组中是否存在所需数据,而不是使用Array.forEach

        然后使用every调用返回的布尔值作为过滤条件来过滤数据。

        Array.forEach 不返回任何内容,但 Array.filter 需要一个布尔谓词进行测试,但在您的代码中 forEach 将返回 undefined

        另外第二个键应该是langSpeak 而不是code

        const usersData = {usersList:[{user:"user1",langSpeak:["IND","SPN"]},{user:"user2",langSpeak:["IND"]},{user:"user1",langSpeak:["IND","SPN","JPN"]},{user:"user3",langSpeak:["IND","SPN"]},{user:"user3"}]};
        
        let usersKey = ["user","langSpeak"];
        let langValues = ["IND","SPN","JPN"];
        let userValues = ["user1"];
        
        let userColl = usersData.usersList.filter(userObj => {
        return usersKey.every( usersKey => {
            if(Array.isArray(userObj[usersKey])){
              return langValues.every(x => {
                  return userObj[usersKey].includes(x)
              });
            }
            else{
              return userValues.every(user => user === userObj[usersKey]);
            } 
         });
        });
        
        console.log(userColl);

        【讨论】:

        • 谢谢阿马尔迪普。但是当我把 let usersKey = ["user","langSpeak"]; let usersValue = ["user1","IND","SPN","JPN"] 那么它应该只有第三个 userList 对象,但在这里我得到了第一和第三。你能否也让我知道这一点。非常感谢
        • @Sammy 请立即查看
        • 不使用额外的 let userValues = 是不可能的吗?
        • @Sammy 这是可能的,但它会很难看,最好将标准分成两个不同的数组。
        【解决方案5】:

        forEach 不返回任何内容 - 稍微更改您的代码以使用 everysome。我还用三元组稍微修改了它:

        const usersData = {
          usersList: [{
              user: "user1",
              langSpeak: ["IND", "SPN"],
            },
            {
        
              user: "user2",
              langSpeak: ["IND"],
            },
            {
        
              user: "user1",
              langSpeak: ["IND", "SPN", "JPN"],
            },
            {
        
              user: "user3",
              langSpeak: ["IND", "SPN"],
            },
            {
              user: "user3"
            }
          ]
        };
        
        let usersKey = ["user", "langSpeak"];
        let usersValue = ["user1", "IND", "SPN"];
        
        let userColl = usersData.usersList.filter(userObj => usersKey.every(k => Array.isArray(userObj[k]) ? usersValue.some(v => userObj[k].includes(v)) : usersValue.includes(userObj[k])));
        
        console.log(userColl);

        【讨论】:

        • 谢谢杰克。但是当我把 let usersKey = ["user","langSpeak"]; let usersValue = ["user1","IND","SPN","JPN"] 那么它应该只有第三个 userList 对象,但在这里我得到了第一和第三。你能否也让我知道这一点。非常感谢
        猜你喜欢
        • 2019-03-18
        • 1970-01-01
        • 2016-02-11
        • 1970-01-01
        • 2021-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-06
        相关资源
        最近更新 更多