在Javascript中过滤多个数组对象并将键值与多个值匹配形成另一个数组

Filter multiple Array Objects and match key values with multiple values form another array in Javascript

我已经绞尽脑汁几个晚上了,我希望好心人能帮助解决我遇到的这堵墙。

我有一个对象数组。

作为用户,我应该能够通过多个或单个过滤器来过滤功能名称。 单个过滤器应 return 所有具有匹配名称的事件 多重过滤器应匹配具有多个特征名称的所有事件,不少于 2 或过滤器数组的长度。

我最终坚持使用的代码或者我能做到的就是这个。

let obj1 = [{
  "results": [{
      "id": "1",
      "name": "Event 1",
      "feature": [{
          "id": {
            "target": "78"
          },
          "name": "Bronze"
        },
        {
          "id": {
            "target": "27"
          },
          "name": "Straw"
        },
        {
          "id": {
            "target": "45"
          },
          "name": "Gold"
        }
      ]
    },
    {
      "id": "2",
      "name": "Event 2",
      "feature": [{
        "id": {
          "target": "20"
        },
        "name": "Straw"
      }]
    },
    {
      "id": "3",
      "name": "Event 3",
      "feature": [{
          "id": {
            "target": "20"
          },
          "name": "Gold"
        },
        {
          "id": {
            "target": "20"
          },
          "name": "Straw"
        }
      ]
    },
    {
      "id": "4",
      "name": "Event 4",
      "feature": [{
          "id": {
            "target": "97"
          },
          "name": "Coal"
        },
        {
          "id": {
            "target": "39"
          },
          "name": "Wood"
        }
      ]
    }
  ]
}]


let filterQuery = ['Straw', 'Gold'];


obj1 = obj1[0].results.filter(r => {
  return r.feature.every(f => {
    return filterQuery.includes(f.name)
  })
})

console.log(obj1);

它用 StrawGold 过滤任何东西,用稻草和金

过滤所有东西

我正在尝试让过滤器过滤 Straw && Gold

所以return用例子

{name: 'Straw', name: 'Gold', name: 'Diamond', name: Copper}

将是一个正确的匹配项,因此用户可以向数组添加另一个过滤器以进一步过滤结果。

{ name: Straw, name: Diamond }

匹配不正确。

任何帮助,建议将不胜感激:)

============================================= ==============

已更新解决方案。我需要它尽可能不可知,以便在键名更改时它能正常工作。用于 Drupal 的 Vuejs 项目。

    export default class FilterData {
    
      constructor(name, data, filter_query) {
        this.name = name;
        this.data = data;
        this.filter_query = filter_query;
      }
    
      filterData(){
        let temp = this.data

// filter out any undefined arrays
        temp = temp.filter((item) => item[this.name] !== undefined);
        temp = temp.filter((item) =>
          [this.filter_query].every((filter) =>
            item[this.name].some(({ name }) => name === filter)
          )
        );
        return temp
      }
    
    }

然后像这样使用它

/* use a temp copy of the returned data from the api
so we can keep refiltering from multiple drop downs, radio, checkboxes changes each time a filter keyname is un-selected.
*/

let apiResults = this.apiData.results;

      let filtered = new FilterData(
        `${keyname}`,
        apiResults,
        this.filterQuery[`${keyname}`]
      );

非常感谢@pilchard,您的回答对此有很大帮助。

您需要将 every() 调用切换到 filterQuery 数组。因此,测试过滤器数组中的 every() 字符串是否在 feature 数组中有匹配项,这里使用 some().

进行测试

let obj1 = [{ "results": [{ "id": "1", "name": "Event 1", "feature": [{ "id": { "target": "78" }, "name": "Bronze" }, { "id": { "target": "27" }, "name": "Straw" }, { "id": { "target": "45" }, "name": "Gold" }] }, { "id": "2", "name": "Event 2", "feature": [{ "id": { "target": "20" }, "name": "Straw" }] }, { "id": "3", "name": "Event 3", "feature": [{ "id": { "target": "20" }, "name": "Gold" }, { "id": { "target": "20" }, "name": "Straw" }] }, { "id": "4", "name": "Event 4", "feature": [{ "id": { "target": "97" }, "name": "Coal" }, { "id": { "target": "39" }, "name": "Wood" }] }] }]

let filterQuery = ['Straw', 'Gold'];

const filteredObj = obj1[0].results.filter(({ feature }) =>
  filterQuery.every(filter =>
    feature.some(({ name }) => name === filter)))

console.log(filteredObj);