4

I have an object like that:

{
  "data": [
    {
      "id": "1234",
      "is_deleted": false,
      "name": "Sarah"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Bobby"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Sartah"
    }
  ]
}

React code

import React from 'react';
import { Input } from 'antd';
import { connect } from 'dva';

const Search = Input.Search;

@connect(({ rule, loading }) => ({
  rule,
  loading: loading.models.rule,
}))

export default class SearchBox extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isListLoaded: false,
            resultArr: {}
        }
    }

    performSearch(value) {
    for( var i = this.props.rule.data.list.length; i--; ) {
        for (var key in this.props.rule.data.list[i]) {
            this.setState({resultArr: this.state.resultArr.push(i)});
            }
    }
    }

    componentDidMount() {
        if (!this.state.isListLoaded) {
            const { dispatch } = this.props;
            dispatch({
                type: 'rule/fetch'
            });
            this.setState({ isListLoaded: true });
    }
  }

  render() {
    return (
      <div>
           <Search
            placeholder="Search..."
                    onChange={(event) => this.performSearch(event.target.value)}
            style={{ width: "250px", "margin-left": "20px"}}
          />
      </div>
    );
  }
}

My goal is very simple: I want to search through this object, and return the entire array(s) that contains the keyword.

Example: if I search "Sar", I should get 2 objects:

{
  "id": "1234",
  "is_deleted": false,
  "name": "Sarah"
},
{
  "id": "3520",
  "is_deleted": true,
  "name": "Sartah"
}

Problem is, I get an error when I'm trying this code. I did search for previous solutions to this problem here on SO, but I can only find examples where there's only one element returned. What I want, is to get ALL the results that contain the keyword in ANY attributes (in this example, I'm returning 2 elements, not just one)

Any idea?

3 Answers 3

12

const { data } = {
  "data": [
    {
      "id": "1234",
      "is_deleted": false,
      "name": "Sarah"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Bobby"
    },
    {
      "id": "3520",
      "is_deleted": true,
      "name": "Sartah"
    }
  ]
};

const keyword = "Sar";

const filtered = data.filter(entry => Object.values(entry).some(val => typeof val === "string" && val.includes(keyword)));

console.log(filtered);

It filters the entries of data Array with the following criterium: at least one of the entry's values must contain a given keyword.

Since IE doesn't yet support Object.values() and String.prototype.includes() you can use the following:

const containsKeyword = val => typeof val === "string" && val.indexOf(keyword) !== -1;

const filtered = data.filter(entry => Object.keys(entry).map(key => entry[key]).some(containsKeyword));

or polyfill these ES6 features, see more here.

To make the keyword lookup case insensitive, you can use RegExp:

const re = new RegExp(keyword, 'i');
const filtered = data.filter(entry => Object.values(entry).some(val => typeof val === "string" && val.match(re)));
Sign up to request clarification or add additional context in comments.

2 Comments

Note that Object.values and String.includes are not supported in IE.
any idea on how to make it case insensitive?
0

Instead of looping through array simply use filter method of javascript

   performSearch(value) {
   const unfilteredData = this.props.rule.data.list;
   const filteredDate = unfilteredData.filter((val) => {
     return val.name.indexOf(val) !== -1;
   });
   this.setState({
      resultArr: filteredDate,
    })
  }

Comments

0
performSearch(value) {
    let filteredData = this.props.rule.data.list.filter(item => {
        let isFiltered = false;
        for(let key in item){
            if(item[key].includes(value)){
                isFiltered = true;
            }
        }
        return isFiltered;
    })
    this.setState({resultArr: filteredData});
}

2 Comments

Could you please add an explanation with your code so that the asker (and future readers) know why there was the problem, as well as know how to fix it.
if(item[key].includes will throw for non-strings.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.