【问题标题】:Return entire objects after filtering not just values that match过滤后返回整个对象,而不仅仅是匹配的值
【发布时间】:2021-03-03 01:41:12
【问题描述】:

我目前正在根据一组值过滤一组对象。我的对象数组如下所示,这个数组定义为 arr1:



[
  {
    "filters": {
      "counties": ["Philadelphia", "Bucks"],
      "gender": ["Male"],
      "rate": ["$300 or less"],
      "experience": ["10 or fewer"],
      "rating": ["10 or fewer"]
    }
  },
  {
    "filters": {
      "counties": ["Montgomery", "Chester"],
      "gender": ["Male"],
      "rate": ["$301-350"],
      "experience": ["11-20"],
      "rating": ["31+"]
    }
  },

  {
  "filters": {
      "counties": ["Philadelphia"],
      "gender": ["Male"],
      "rate": ["$301-350"],
      "experience": ["11-20"],
      "rating": ["31+"]
    }
  }
]


我将对象数组与如下所示的数据结构进行比较,该对象定义为 obj:

{
"counties": ["Philadelphia", "Bucks"],
"gender": ["Male"],
"experience": ["10 or fewer"],
"rating": ["10 or fewer"]
}

我可以通过执行以下操作来过滤县:

    arr1.map((item) => {
      item.filters.counties.filter((i) => {
        if (obj.counties.includes(i)) {
          console.log(item)
          return item
        }
      })
    })

控制台日志成功返回 arr1 中包含费城的所有对象,但我没有正确返回。我想知道,一个接一个地堆叠这些过滤器的最佳方式。我目前有些不知所措。我创建了一个用于调试的代码框https://codesandbox.io/s/ecstatic-hodgkin-pwlyg?file=/src/index.js

所需的结果:返回 arr1 中与与之比较的数组映射匹配的所有对象

【问题讨论】:

  • 您是要匹配任何个字段还是所有个字段?
  • 对不起,你能解释一下区别,以便我给你一个可靠的答案
  • 如果它与性别不匹配,则不应包含在内,对于任何混淆,我深表歉意
  • 所以基本上一个标准匹配,如果它和对象之间有任何重叠?我会重新审视我的答案。
  • 是的,我相信这是我想要实现的行为

标签: javascript reactjs


【解决方案1】:

const arr1 = [
  {
    filters: {
      counties: ["Philadelphia", "Bucks"],
      gender: ["Male"],
      rate: ["$300 or less"],
      experience: ["10 or fewer"],
      rating: ["10 or fewer"]
    }
  },
  {
    filters: {
      counties: ["Montgomery", "Chester"],
      gender: ["Male"],
      rate: ["$301-350"],
      experience: ["11-20"],
      rating: ["31+"]
    }
  },

  {
    filters: {
      counties: ["Philadelphia"],
      gender: ["Male"],
      rate: ["$301-350"],
      experience: ["11-20"],
      rating: ["31+"]
    }
  }
];


const obj = {
  counties: ["Philadelphia", "Bucks"],
  gender: ["Male"],
  experience: ["10 or fewer"],
  rating: ["10 or fewer"]
};


let output = [];
arr1.map((item) => {
  return item.filters.counties.filter((i) => {
    if (obj.counties.includes(i)) {
      console.log(item);
      output.push(item);
      return item;
    }
    return null;
  });
});

console.log("-----------------------------------");
console.log(output); // if you need to take retured values

您可以使用Array 收集包含在object.countries 中的所有项目

【讨论】:

  • 如果我想堆叠过滤器,你会先收集县匹配然后过滤性别等
【解决方案2】:

如果您只想返回国家列表中包含“费城”或“雄鹿”的过滤器,您可以减少过滤器。您需要通过检查约束是否包含过滤器的任何(某些)值来保留与每个约束匹配的过滤器。

const filters = arr1.reduce((acc, item) =>
  Object.entries(obj).every(([key, val]) =>
      val.some(v => item.filters[key].includes(v)))
    ? [...acc, item ] : acc);

这也可以用作过滤器,而不是减速器。这允许该项目被破坏(拉出filters),因为我们不再需要归还它。

const filteredFilters = arr1.filter(({ filters }) =>
  Object.entries(obj).every(([key, val]) =>
      val.some(v => filters[key].includes(v))));

注意:我给了arr1(现在是globalFilters)和obj(现在是criteria)更多的描述性名称。它有助于弄清楚发生了什么。

const globalFilters = [{
  "filters": {
    "counties": ["Philadelphia", "Bucks"],
    "gender": ["Male"],
    "rate": ["$300 or less"],
    "experience": ["10 or fewer"],
    "rating": ["10 or fewer"]
  }
}, {
  "filters": {
    "counties": ["Montgomery", "Chester"],
    "gender": ["Male"],
    "rate": ["$301-350"],
    "experience": ["11-20"],
    "rating": ["31+"]
  }
}, {
  "filters": {
    "counties": ["Philadelphia"],
    "gender": ["Male"],
    "rate": ["$301-350"],
    "experience": ["11-20"],
    "rating": ["31+"]
  }
}];

const criteria = {
  "counties": ["Philadelphia", "Bucks"],
  "gender": ["Male"],
  "experience": ["10 or fewer"],
  "rating": ["10 or fewer"]
};

const filters = globalFilters.reduce((acc, item) =>
  item.filters.counties.find(country => criteria.counties.includes(country))
    ? [...acc, item ] : acc, []);

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

如果您想按所有标准进行过滤,您可以混合一些/每个来评估数组中项目的存在。

const globalFilters = [{
  "filters": {
    "counties": ["Philadelphia", "Bucks"],
    "gender": ["Male"],
    "rate": ["$300 or less"],
    "experience": ["10 or fewer"],
    "rating": ["10 or fewer"]
  }
}, {
  "filters": {
    "counties": ["Montgomery", "Chester"],
    "gender": ["Male"],
    "rate": ["$301-350"],
    "experience": ["11-20"],
    "rating": ["31+"]
  }
}, {
  "filters": {
    "counties": ["Philadelphia"],
    "gender": ["Male"],
    "rate": ["$301-350"],
    "experience": ["11-20"],
    "rating": ["31+"]
  }
}];

const criteria = {
  "counties": ["Philadelphia", "Bucks"],
  "gender": ["Male"],
  "experience": ["10 or fewer"],
  "rating": ["10 or fewer"]
};

const filters = globalFilters.reduce((acc, item) =>
  Object.entries(criteria).every(([key, val]) =>
      val.some(v => item.filters[key].includes(v)))
    ? [...acc, item ] : acc);

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

【讨论】:

  • 在这种情况下,我该如何堆叠这些过滤器?假设用户正在输入特定的过滤器。它们将保持相同的数据格式,只需要能够堆叠它们。 PS我用的是最上面的例子
【解决方案3】:

我建议获取所有过滤器键并遍历数组以检查特定属性是否至少包含过滤器各自数组中的 1 个值。

const arr1 = [
  {
    filters: {
      counties: ["Philadelphia", "Bucks"],
      gender: ["Male"],
      rate: ["$300 or less"],
      experience: ["10 or fewer"],
      rating: ["10 or fewer"]
    }
  },
  {
    filters: {
      counties: ["Montgomery", "Chester"],
      gender: ["Male"],
      rate: ["$301-350"],
      experience: ["11-20"],
      rating: ["31+"]
    }
  },

  {
    filters: {
      counties: ["Philadelphia"],
      gender: ["Male"],
      rate: ["$301-350"],
      experience: ["10 or fewer"],
      rating: ["10 or fewer"]
    }
  }
];

const obj = {
  counties: ["Philadelphia", "Bucks"],
  gender: ["Male"],
  experience: ["10 or fewer"],
  rating: ["10 or fewer"]
};

const filterList = Object.keys(obj);
const filtered = arr1.filter((item) => {
  // get an array of respective filter states
  const res = filterList.map((filterName) =>
    // check if item's particular field contains at least 1 value from 'filters' obj.
    obj[filterName].some((el) => item.filters[filterName].includes(el))
  );
  // return only items for whom all filters are 'true'
  return res.every((el) => el);
});
console.log(filtered);

【讨论】:

    【解决方案4】:

    更新:基于 cmets 将 every 更改为 some

    这样的事情可能会做:

    const filterAll = (criteria) => (objects) =>
      objects .filter (({filters}) => Object .entries (criteria) .every (
       ([k, val]) => val .some (v => filters [k] .includes (v))
      ))
      
    
    const arr1 = [{filters: {counties: ["Philadelphia", "Bucks"], gender: ["Male"], rate: ["$300 or less"], experience: ["10 or fewer"], rating: ["10 or fewer"]}}, {filters: {counties: ["Montgomery", "Chester"], gender: ["Male"], rate: ["$301-350"], experience: ["11-20"], rating: ["31+"]}}, {filters: {counties: ["Philadelphia"], gender: ["Male"], rate: ["$301-350"], experience: ["11-20"], rating: ["31+"]}}]
    const obj = {counties: ["Philadelphia", "Bucks"], gender: ["Male"], experience: ["10 or fewer"], rating: ["10 or fewer"]}
    
    console .log (filterAll (obj) (arr1))
    .as-console-wrapper {max-height: 100% !important; top: 0}

    我们通过查看条件对象的每个属性来过滤对象,然后检查目标字段中的每个条目是否都包含在过滤器对象中。

    这个答案仍然涉及一个猜测。

    是否反对:

    {filters: {counties: ['A', 'B', 'C'], ...}}
    

    匹配条件

    {counties: ['A', 'B'], ...}
    

    因为条件字段中的每一个都包含在对象中?还是因为对象('C')中的值未包含在条件中而导致不匹配?我的假设是前者,但两者都有道理。

    旧代码

    const filterAll = (criteria) => (objects) =>
      objects .filter (({filters}) => Object .entries (criteria) .every (
       ([k, val]) => val .every (v => filters [k] .includes (v))
      ))
    

    注意变化:

       ([k, val]) => val .some (v => filters [k] .includes (v))
       //                 ^^^^
    

    【讨论】:

    • 我注意到,当我尝试实现此代码时,我的主数组中只有 4 个对象被返回。我想知道这可能是什么原因
    • 已更新以处理我认为的真正需求。
    • 在此更新中,我注意到只有一个对象被返回,即使其中一个对象包含 philadelphia
    • 但是experiencerating 不匹配。我以为您想匹配 所有 标准。我认为您应该edit 提供有关哪些对象应该匹配以及为什么匹配的信息。
    • 有可能不会应用所有过滤器
    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 2023-03-14
    相关资源
    最近更新 更多