0

I know this been answered multiple times but I can't seem to find an answer based on my situation. I have two arrays:

words ['word1', 'word2', 'word3']
texts [
    {name: 'blah', description: 'word4'},
    {name: 'blah2', description: 'word1'},
    {name: 'blah3', description: 'word5'}
]

I am trying to filter the two arrays and return true if there is a match

I have seen several examples of simple arrays of numbers but that does not apply here.

Jason
  • 1,091
  • 4
  • 19
  • 40
  • 4
    what is the expected output? – Abhyudit Jain Mar 01 '19 at 18:53
  • true (1) if there is a match – Jason Mar 01 '19 at 18:54
  • Possible duplicate of [Check if object value exists within a Javascript array of objects and if not add a new object to array](https://stackoverflow.com/questions/22844560/check-if-object-value-exists-within-a-javascript-array-of-objects-and-if-not-add) Or [Find object by id in an array of JavaScript objects](https://stackoverflow.com/q/7364150/215552) – Heretic Monkey Mar 01 '19 at 18:57

3 Answers3

3

You can iterate texts using Array.prototype.some() and check for matches in words using Array.prototype.includes(). This is O(nm) time complexity if the length of words and texts are n and m respectively.

const words = ['word1', 'word2', 'word3']
const texts = [
    {name: 'blah', description: 'word4'},
    {name: 'blah2', description: 'word1'},
    {name: 'blah3', description: 'word5'}
]

console.log(
  texts.some(
    ({ description }) => words.includes(description)
  )
)

Another solution that's O(n + m) time complexity uses Set.prototype.has() instead, but this approach will likely be negligibly faster or even a little slower if words is a small array, so only use this if words is extremely large.

const words = new Set(['word1', 'word2', 'word3'])
const texts = [
    {name: 'blah', description: 'word4'},
    {name: 'blah2', description: 'word1'},
    {name: 'blah3', description: 'word5'}
]

console.log(
  texts.some(
    ({ description }) => words.has(description)
  )
)

Update

To address your issue regarding case-sensitivity, I recommend a somewhat different approach. Since both arrays will contain words with mixed casing, convert one of the arrays to regular expressions and test each regular expression against all the words in the other array with the case-insensitive flag.

const words = ['word1', 'WORD2', 'Word3']
const texts = [
    {name: 'blah', description: 'Word4'},
    {name: 'blah2', description: 'Word1'},
    {name: 'blah3', description: 'Word5'}
]

console.log(
  texts.some(({ description }) => {
    const regexp = new RegExp(description, 'i')      
    return words.some(word => regexp.test(word))
  })
)

If your words contain non-alphanumeric characters as well, I highly suggest you borrow this function to escape your regular expressions properly. If you don't escape them, you could potentially end up with cases like below causing your code to throw errors or provide incorrect results.

function escapeRegExp(text) {
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}

const words = ['?WORD1', 'word2', 'Word3']
const texts = [
    {name: 'blah', description: 'Word4'},
    {name: 'blah2', description: '?Word1'},
    {name: 'blah3', description: 'Word5'}
]

console.log(
  texts.some(({ description }) => {
    const regexp = new RegExp(escapeRegExp(description), 'i')      
    return words.some(word => regexp.test(word))
  })
)
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • Hey Patrick I have a new issue. I need to make the search case insensitive. I can do this in words.includes(description. toLowerCase()) but I can't figure out how to handle texts.some(({description}) Any ideas? – Jason Mar 01 '19 at 23:03
2

You can use filter and includes together to know which word is present in the object

var words= ['word1', 'word2', 'word3']
var texts=[
    {name: 'blah', description: 'word4'},
    {name: 'blah2', description: 'word1'},
    {name: 'blah3', description: 'word5'}
]
console.log(texts.filter((x)=>words.includes(x.description)).length>0?true:false)
ellipsis
  • 12,049
  • 2
  • 17
  • 33
1

I think this will solve your issue:

const words = ['word1', 'word2', 'word3']
const texts = [
    {name: 'blah', description: 'word4'},
    {name: 'blah2', description: 'word1'},
    {name: 'blah3', description: 'word5'}
]

function check(arra, arrb) {
return !!texts.find(_text => words.includes(_text.description))
}

console.log(check(words, texts))
John Vandivier
  • 2,158
  • 1
  • 17
  • 23
  • The only caveat is that this approach will be incorrect if any of the `words` are an empty string and a match is found. It would be better to explicitly `!== undefined` rather than use double negation. – Patrick Roberts Mar 01 '19 at 19:16