0

I have an array of names;

["Agent 1", "Agent 12", "Agent 2"]

I will receive a string (that may or may not contain one of the words in the array) that I need to search through and, if a match is found, return the array value.

For example, I may receive the string.

I spoke to Agent 1 the other day.

I use the following algorithm to search for any matches.

for (var i in agent_names) {
    var name = agent_names[i];

    if (msg.toLowerCase().indexOf(name.toLowerCase()) !== -1) {
        return agent_names[i];
    }
}

return null;

This works fine for Agent 1. However if the same message said;

I spoke to Agent 12 the other day.

The algorithm will still match Agent 1 as it is part of the string.

Essentially, I am looking for a best fit search rather than first fit. indexOf does not work in this instance.

The only way I can think of doing this is brute forcing it by letter and storing the longest match. But this seems inefficient?

  • It sounds like you're looking for a fuzzy search to determine the best match for your string. There are a lot of answers and debates on methodologies, but why not settle on a small 8kb library that does this for you? https://github.com/Glench/fuzzyset.js – hotforfeature Jun 08 '16 at 04:23
  • Also be sure to check out http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea and avoid using `for...in` for array iteration – hotforfeature Jun 08 '16 at 04:24
  • A fuzzy search is a step too far. The longest match will always be preferred. And i'll check out that `for...in` thread. – Pejman Poh Jun 08 '16 at 04:51

4 Answers4

1

Sort your array of words before matching loop begins :

agent_names = agent_names.sort(function(i,j){return i.length < j.length})
for (var i in agent_names) {
    var name = agent_names[i];

    if (msg.toLowerCase().indexOf(name.toLowerCase()) !== -1) {
        return agent_names[i];
    }
}

return null; 
Nikhil Maheshwari
  • 2,198
  • 18
  • 25
0

Order the list of strings by length descending.

Qwertiy
  • 19,681
  • 15
  • 61
  • 128
0

Use regex.

reg = '\\b(' + name.toLowerCase() + ')\\b'; 
if (msg.toLowerCase().indexOf(reg) !== -1) {
    return agent_names[i];
}

This will ensure that you are looking for the search term within word boundaries so you won't accidentally match 'Agent 13' or 'Agent 12' when looking for 'Agent 1'

phreakv6
  • 2,135
  • 1
  • 9
  • 11
0

.match(/\d+/) will return number from string .So store number array agent_names and get the greatest number by Math.max.Then you can replace your string by replace.

var name_arr = [];
for (var i in agent_names) {        
    name_arr.push(agent_names[i].match(/\d+/));//store number array
}
replace_text = Math.max.apply(Math,name_arr);//get greatest number
msg = msg.replace("1",replace_text); //replace with greatest number
console.log(msg);
Jack jdeoel
  • 4,554
  • 5
  • 26
  • 52