2

I want to use Lodash to return true when an object contains in any of its values, a match for a partial string. I've tried this with _.includes as follows.

const ob = {first: "Fred", last: "Flintstone",}
const search = "stone";
const result = _.includes(ob, search)
console.log(result); // false

I've also tried this using a regular expression instead of a string for the search term.

const search = /stone/gi;

Both times result returns false. I want result to return true. How can I do this in Lodash?

Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207

4 Answers4

8

You can use lodash's _.some() (which works with objects), and lodash/vanilla includes to find if the current property's value has the search string:

const includesValue = (val, obj) => _.some(obj, v => _.includes(v, val))

const obj = {first: "Fred", last: "Flintstone",}
const search = "stone";
const result = includesValue(search, obj)

console.log(result); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

And a lodash/fp version:

const includesValue = val => _.some(_.includes(val))

const obj = {first: "Fred", last: "Flintstone",}
const search = "stone";
const result = includesValue(search)(obj)

console.log(result); // true
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

To handle case sensitivity and letters with diacritics, you can use _.deburr() (or the this answer), and convert the text to lower case:

const normalize = str => _.toLower(_.deburr(str))

const includesValue = (val, obj) => {
  const search = normalize(val)
  return _.some(obj, v => normalize(v).includes(search))
}

const obj = {first: "Fred", last: "Flintstoné",}
const search = "Stone";
const result = includesValue(search, obj)

console.log(result); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • How would you recommend to make it case insensitive? And match accents so that "éèe" are treated as identical? – Vadorequest Nov 28 '19 at 17:58
  • Found https://stackoverflow.com/a/37435964/2391795 which helped me implement insensitive case matching – Vadorequest Nov 28 '19 at 18:15
  • 1
    Thanks for the edit. I've added the last solution that handles letters with diacritics and insensitive checks. – Ori Drori Nov 28 '19 at 18:45
  • 1
    Interesting that you used deburr, I implemented another solution using https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript, which gives `return includes( mostInterestingValue.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, ''), searchedValue.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, ''), );` and works fine. Not sure what the differences are, but yours seems much simpler to reason about. – Vadorequest Nov 29 '19 at 11:26
1

You could find the string partial within an array of the object's values like this.

const ob = {
  first: "Fred",
  last: "Flintstone"
}
const search = "stone"
const isFound = Boolean(Object.values(ob).find(item => item.includes(search)))
console.log(isFound)

And as per @Kobe's suggestion, you could use some instead of evaluating the result of find with Boolean().

const ob = {
  first: "Fred",
  last: "Flintstone"
}
const search = "stone"
const isFound = Object.values(ob).some(item => item.includes(search))
console.log(isFound)
ksav
  • 20,015
  • 6
  • 46
  • 66
0

That's not how lodash's includes works.

You should search the values of the object, not the object itself. And you should check each value in turn.

Also you don't need lodash for that.

const ob = {first: "Fred", last: "Flintstone",}
const search = "stone";
const result = Object.values(ob).some(value => value.indexOf(search) !== -1);
console.log(result); // true
Harijs Deksnis
  • 1,366
  • 1
  • 13
  • 24
0

You could use _filter if you want to use lodash.

const ob = {first: "Fred", last: "Flintstone",}
var filteredOb = _.filter(ob, function(elem) {
    return elem.indexOf("stone") > -1;
});
console.log(filteredOb);
MrDeibl
  • 157
  • 1
  • 10