【问题标题】:Filter an array of objects by another object of filters通过另一个过滤器对象过滤一个对象数组
【发布时间】:2021-10-30 18:33:50
【问题描述】:

我有一组遵循以下结构的对象:

{
  "level": 1
  "objectId": "3756"
  "objectIdNo": 35636
  "wpId": "3635473"
}

我现在想用另一个对象过滤这些对象的数组。这个filterObject 的结构如下:

// filterObject
{
  level: "2"
  objectId: "10"
  wpId: "1"
}

但是filterObject 并不总是包含所有键值对,因为它们是在 UI 中手动设置的。因此,filterObject 也可以如下所示:

{
  level: "2"
}

我的目标是返回与 filterObject 匹配的 filteredObjects 的新数组。当filterObject 上只存在一个过滤器时,我想返回与这一个键值对匹配的所有对象。但是如果filterObject 上存在更多过滤器,我想返回匹配两个键值对(不仅仅是一个)的所有对象。

示例:

这是我要过滤的数据:

[
  {
    "level": "1"
    "objectId": "11"
    "objectIdNo": "320"
    "wpId": "123"
  },
  {
    "level": "2"
    "objectId": "12"
    "objectIdNo": "321"
    "wpId": "123"
  },
  {
    "level": "2"
    "objectId": "13"
    "objectIdNo": "322"
    "wpId": "120"
  },
]

1.

如果这是我的filterObject:

{
  "level": "2"
}

返回:

[
  {
    "level": "2"
    "objectId": "12"
    "objectIdNo": "321"
    "wpId": "123"
  },
  {
    "level": "2"
    "objectId": "13"
    "objectIdNo": "322"
    "wpId": "120"
  },
]

2.

如果这是我的filterObject:

{
  "level": "2",
  "wpId": "123"
}

返回:

[
  {
    "level": "2"
    "objectId": "12"
    "objectIdNo": "321"
    "wpId": "123"
  },
]

我希望这能解释我想要实现但我自己无法实现的逻辑。我会很感激一些想法或适用的功能。

这是我已经在 React 中尝试过的。 data 变量保存对象数组,filter 变量保存filterObjects

useEffect(() => {
    if (data) {
      const filtered = data.filter((task) => {
        if (!filter) {
          return true;
        }
        return (
          task.level === filter.level ||
          task.objectId === filter.objectId ||
          task.wpId === filter.wpId
        );
      });
      setFilteredTasks(filtered);
    }
  }, [filter]);

通过我的尝试,如果我只设置一个过滤器键值对,我会得到一个空数组,

【问题讨论】:

标签: javascript arrays reactjs filter


【解决方案1】:

您可以使用filterObject.keysevery 实现此结果。

您必须使用filter 并传递谓词来判断它是否包含在最终结果中。

在谓词中,遍历filters 对象上的所有属性,并匹配它是否存在于data 中。简单

data.filter((o) =>Object.keys(filters).every((k) => filters[k] === o[k]));

const data = [{
    level: "1",
    objectId: "11",
    objectIdNo: "320",
    wpId: "123",
  },
  {
    level: "2",
    objectId: "12",
    objectIdNo: "321",
    wpId: "123",
  },
  {
    level: "2",
    objectId: "13",
    objectIdNo: "322",
    wpId: "120",
  },
];

const filters = {
  level: "2",
  wpId: "123",
};

const result = data.filter((o) =>
  Object.keys(filters).every((k) => filters[k] === o[k])
);
console.log(result);

【讨论】:

    【解决方案2】:

    这应该可以解决问题!

    const exampleData = [
      {
        "level": "1",
        "objectId": "11",
        "objectIdNo": "320",
        "wpId": "123",
      },
      {
        "level": "2",
        "objectId": "12",
        "objectIdNo": "321",
        "wpId": "123",
      },
      {
        "level": "2",
        "objectId": "13",
        "objectIdNo": "322",
        "wpId": "120",
      },
    ];
    
    const filterObject1 = {
      "level": "2",
    }
    
    const filterObject2 = {
      "level": "2",
      "wpId": "123"
    }
    
    
    function filter(data, filterObject) {
      const filterValues = Object.entries(filterObject)
      
      let filteredData = data
      for(const [filterKey, filterValue] of filterValues) {
        filteredData = filteredData.filter(obj => obj[filterKey] === filterValue)
      }
      return filteredData
    }
    
    
    
    console.log(filter(exampleData, filterObject1))
    console.log(filter(exampleData, filterObject2))

    【讨论】:

      【解决方案3】:

      你可以这样做:

      const data = [
        {
          level: "1",
          objectId: "11",
          objectIdNo: "320",
          wpId: "123",
        },
        {
          level: "2",
          objectId: "12",
          objectIdNo: "321",
          wpId: "123",
        },
        {
          level: "2",
          objectId: "13",
          objectIdNo: "322",
          wpId: "120",
        },
      ];
      
      const filterObject = {
        level: "2",
        wpId: "123",
      };
      
      const result = data.filter((item) => {
        let flag = true;
        Object.keys(filterObject).forEach((key) => {
          if (item[key] !== filterObject[key]) {
            flag = false;
            return;
          }
        });
        return flag;
      });
      
      console.log(result);

      【讨论】:

        【解决方案4】:

        const input = [ { "level": "1", "objectId": "11", "objectIdNo": "320", "wpId": "123" }, { "level": "2", "objectId": "12", "objectIdNo": "321", "wpId": "123", }, { "level": "2", "objectId": "13", "objectIdNo": "322", "wpId": "120" }, ]
        
        const filter = { "level": "2", "wpId": "123" };
        
        const filteredOutput = input.filter( obj => {
          return Object.keys(filter).every( filterKeys => {
            return obj[filterKeys] === filter[filterKeys]
          });
        });
        
        console.log(filteredOutput);

        【讨论】:

        • 其他人实现它的速度更快,但无论如何它就在这里