【问题标题】:Searching through multiple properties in an object using only one input aka global search仅使用一个输入(即全局搜索)搜索对象中的多个属性
【发布时间】:2019-05-14 16:30:22
【问题描述】:

我正在尝试仅使用一个文本输入为 reactjs 中的对象构建通用/全局搜索。

我尝试了不同的方法,包括将字符串转换为数组,然后使用它来过滤我的对象。我设法通过所有属性进行输入搜索,但当时只有一个。

const data = [
  {
    name:"Italy",
    title:"Best place for Pizza"
  },
  {
    name:"USA",
    title:"It is a federal state"
  }
]
export class MyApp extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      filteredData:[],
      filter:''
    }
    this.handleSearch.bind(this);
  }
  componentDidMount(){
    this.setState({
      filteredData:data
    })
  }

  handleSearch = (e) =>{
    const filter = e.target.value;

    this.setState({
      filter
    })
  }
  render(){
    var filteredData = data;
    var searchValue = this.state.filter;
    filteredData = filteredData.filter(country => {
      return['name', 'title'].some(key =>{
        return country[key].toString().toLowerCase().includes(searchValue)
      })
    })

    return (
      <div>
        <input type="search" onChange={(e) => this.handleSearch(e)}/>
        {
          filteredData.map(result =>{
              return <p>{result.name} | {result.title}</p>
          })
        }
      </div>
    );
  }

我想要的是能够组合属性。例如:我希望能够输入“Italy best place for...”并仍然得到结果。我不想仅限于输入“披萨的最佳地点”或“意大利”来获得条目。

【问题讨论】:

  • 这是您正在寻找的模糊搜索类型吗?

标签: javascript arrays reactjs object


【解决方案1】:

你可以让你的搜索做这样的事情:

const data = [ { name:"Italy", title:"Best place for Pizza" }, { name:"USA", title:"It is a federal state" } ]

let search = (arr, str) => {
 return arr.filter(x => Object.values(x)
  .join(' ')
  .toLowerCase()
  .includes(str.toLowerCase()))
}

console.log(search(data, 'Italy best'))
console.log(search(data, 'USA it is'))

这个想法是使用Array.filter并在里面获取对象的值(使用Object.values)(这里我们假设它们都是字符串)并将它们(通过Array.join)组合成一个字符串。然后用Array.includes在里面搜索。

【讨论】:

  • 太棒了!它完美地工作。一个问题是,是否有任何方法可以按任何顺序输入标准?例如标题+名称。 (我知道,这与我的要求有点牵强。这对我来说不是必须的,更像是一个不错的选择)谢谢!​​
  • 是的,它有些不同,但您也可以再次添加字段并切换它们的位置。就像反转数组一样,现在标题是第一个,名称是第二个。它可能会变得多毛,但在大多数情况下都会起作用。如果此答案对您有所帮助,请确保您标记它,以便其他人可以找到它。谢谢!
【解决方案2】:

我不确定这是否是最佳实践,但当我遇到类似问题时,我只是不断地将我的 .filter() 函数相互链接,每个过滤器都搜索不同的属性。

filteredData = filteredData.filter(country => {
    return country['name'].toString().toLowerCase().includes(searchValue)
      }).filter(country => {
    return country['title'].toString().toLowerCase().includes(searchValue)
    })

它有效,但看起来不那么漂亮。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-01
    • 2018-05-06
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 2018-08-17
    • 2020-06-23
    相关资源
    最近更新 更多