【问题标题】:How to filter out multiple objects values including nested object value with matching string?如何过滤掉多个对象值,包括匹配字符串的嵌套对象值?
【发布时间】:2021-02-01 19:13:34
【问题描述】:
import { createSelector } from 'reselect';


let exampleState = {
  shop: {
    matchingWord: "bmw",
    cars: [
      { name: 'bmw', value: 130, comments: "expensive car" },
      { name: 'mercedes', value: 295, comments:"good looking" },
      { name: 'toyota', value: 95, comments:{ review: "bmw is better" } },
    ]
  }
}

const filteredCarsSelector = createSelector(
  (state) => state.shop.cars,
  (state) => state.shop.matchingWord,
  (cars, filters) =>
    cars.filter((car) => {
      return Object.values(car).some((word) => {
        return typeof word === "string" && word.toLowerCase().includes(filters);
      });
    })
)

console.log(filteredCarsSelector(exampleState))

使用 reselect redux 库中的 createSelector,我试图过滤掉匹配单词的对象。所以在这个例子中,现在当我 console.log(filteredCarsSelector(exampleState)) 时,我得到[{ name: 'bmw', value: 130, comments: "expensive car" }],因为我的方法只检查顶级对象键并且不检查嵌套对象键,如“review”来查找匹配词,但我试图让两个对象都包含“bmw”,所以当我使用 console.log 时,我希望结果是这样的 [{ name: 'bmw', value: 130, comments:"expensive car"},{ name: 'toyota', value: 95, comments: {review: "bmw is better" }}] ,因为名称的值和评论的值都包含“bmw”。这里的技巧是审查键嵌套在 cmets 内。 有没有办法可以结合“car.name”和“car.cmets.review”来过滤掉包含匹配词的对象?这是codeandbox的链接:https://codesandbox.io/s/epic-glade-lls2w?file=/src/App.js

【问题讨论】:

    标签: javascript reactjs redux react-redux


    【解决方案1】:

    有 3 个选项:

    1. 如果您事先知道搜索令牌的位置,您可以将过滤功能更改为
    return Object.values(car).some((word) => {
      if(typeof word === "string") return word.toLowerCase().includes(filters) ;
      if(typeof word === "object") return word.review.toLowerCase().includes(filters);
      // ... add all possible combinations
      return false
    });
    
    1. 如果您不这样做,最简单的方法是序列化您的对象,然后...搜索它
    return Object.values(car).some((word) => {
      return JSON.stringify(word).toLowerCase().includes(filters)
    });
    
    1. 您可以使用递归过滤器函数。像这样的
    const searchRecur = (tokens, obj)=>{
      // Handle strings, numbers, undefined and null
      if(typeof(obj) !== "object") return (obj + "").toLowerCase().includes(tokens);
      if(obj == null) return false;
      
      // Handle objects (and arrays)
      for(let val of Object.values(obj)){
        if(searchRecur(tokens, val)) return true;
      } 
      
      return false;
    }
    
    
    const filteredCarsSelector = createSelector(
      ...
      (cars, filters) => {
        const myFilter = searchRecur.bind(null, filters);
        return cars.filter(myFilter)
      }
    );
    

    正如我所说,最简单的方法是序列化对象。

    【讨论】:

    • 感谢您的帮助,序列化对象成功了!但我不确定它为什么会起作用。 JSON.stringify 将对象键转换为字符串,我不明白这如何检索嵌套对象值。
    • 您可能想再看看JSON.stringifyJSON.parse 文档。 JSON.stringify({"name":"bmw","value":130,"comments":"expensive car","nested":{"anotherObjct":{"key1":"value1"}}}) 会给你"{"name":"bmw","value":130,"comments":"expensive car","nested":{"anotherObjct":{"key1":"value1"}}}"JSON.parse 也同样有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 2021-05-06
    • 2020-11-01
    • 2020-07-03
    • 2021-08-01
    • 2017-01-28
    相关资源
    最近更新 更多