Using filter() in combination with includes() to get partial matches

Viewed 8728

I have an array with objects I want to search through. The searchable array looks like this:

[
    { value: 0, label: 'john' },
    { value: 1, label: 'johnny' },
    { value: 2, label: 'peter' },
    { value: 3, label: 'peterson' }
]

I search through this using the Lodash filter method:

search = (text) => {
    let results = _.filter(
        this.props.options,
        { label: text }
    );
}

This only shows the result that exactly matches the search query (text parameter). I need to make this work with partial matches. So if I insert j or johnny it should be able to find both 'John' and 'Johnny'.

I have tried:

search = (text) => {
    let results = _.filter(
        this.props.options => 
            this.props.options.includes({ label: text })
    );
}

But, no luck. No error and no results. How can I make this work?

3 Answers

Since you are using includes which is a part of ES6 standat, then I would solve this task with the ES6 Array.prototype.filter instead of lodash-filter:

let search = (list, text) =>
  list.filter(i => i.label.toLowerCase().includes(text.toLowerCase()));

let list = [
    { value: 0, label: 'john' },
    { value: 1, label: 'johnny' },
    { value: 2, label: 'peter' },
    { value: 3, label: 'peterson' }
];

let result = search(list, 'j');

console.log(result); // [{value: 0, label: "john"}, {value: 1, label: "johnny"}]

Also, with .toLowerCase you may use "John" instead of "john".

String#includes accepts a string as a needle. If the the needle is not a string, it's converted to string, and it the case of an object it's [object Object].

You should get the value of label, and use the string's includes method:

const options = [
    { value: 0, label: 'john' },
    { value: 1, label: 'johnny' },
    { value: 2, label: 'peter' },
    { value: 3, label: 'peterson' }
];

const search = (text) => options.filter(({ label }) => label.includes(text));

const result = search('jo');

console.log(result);

That's not how you use String.prototype.includes. You should provide a string to it not an object. And you should provide a function that wraps the call to includes:

search = (text) => {
    let results = _.filter(
        this.props.options,                             // first parameter to _.filter is the array
        option => option.label.includes(text)           // the second parameter is a funtion that takes an option object and returns a boolean (wether the label of this option includes the text text or not)
    );
}
Related