Home > Back-end >  search for an input in an array returning the reverse of the search input
search for an input in an array returning the reverse of the search input

Time:12-07

I am looking for a way to search for a name within an array, including situations where the search input (of multiple words: first name, surname) may be reversed.

The array would look like this with a series of names.

const names = ['Alan Hope', 'Greg Day', 'Alan Peters']

The search input could be as follows 'peter Al'

What would the code look like to achieve this. This is what I have so far and I know it is totally wrong.


const studentNames = ['Alan Hope', 'Greg Day', 'Alan Peters']

function search () {
  const bankingSheet = ss.getSheetByName('Banking')
  const searchInput = 'Hope Al'
  const searchWords = searchInput.split(/\s /)

  const filtered = studentNames.filter(function(name) {
    searchWords.every(function(word) {
      return name.toString().toLowerCase().indexOf(word) !== -1
    })  
})
Logger.log(filtered)
}

From what I gather I need to first split the search input into the constituent words. I then need to filter through the names array. For each name in the array I need to check if all search words appear in some way in the name. I think this may involve the every method.

For each name, if the return value is true that is what I need to return.

Is this thinking correct?

Here is what I was hoping to replicate from a Youtube video I found along the same lines

Thank you in advance! This is really hurting my head at the moment!

CodePudding user response:

The idea is to define what's meant by a match. The simplest and most rigid match is simple string equality. A softer match would tolerate case differences. Softer still would be a tolerance for a first name / last name inversion. (shown in the snippet).

Softest of all would be a match that tolerates small differences in the names (a reordering would not register as a small difference via a levenshtein check), unless we compared distances between individual tokens).

const names = ['Alan Hope', 'Greg Day', 'Alan Peters']

function softMatch(nameA, nameB) {
  if (nameA === nameB) return true;  

  const reverse = name => name.split(' ').reverse().join(' ')
  
  const lcA = nameA.toLowerCase();
  const lcB = nameB.toLowerCase();
  
  if (lcA === lcB) return true; // case insensitive
  if (reverse(lcA) === lcB) return true;  // order and case insensitive
  return false
}

let matches = names.filter(name => softMatch(name, 'peters Alan'))
console.log(matches)

matches = names.filter(name => softMatch(name, 'No Match'))
console.log(matches)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

If names are to have more than two subnames, and any ordering is a match, then a match can be implemented as follows...

const names = ['Alan Randolph Hope', 'Greg Herbert Walker Day', 'Alan Jefferson Peters']

function softMatch(nameA, nameB) {
  let subnamesA = nameA.split(' ').map(n => n.toLowerCase())
  let subnamesB = nameB.split(' ').map(n => n.toLowerCase())
  
  // sort lexically and compare
  subnamesA = subnamesA.sort();
  subnamesB = subnamesB.sort();

  return subnamesA.every(function(element, index) {
    return element === subnamesB[index]; 
  });
}

let matches = names.filter(name => softMatch(name, 'peters Alan jefferson'))
console.log(matches)

matches = names.filter(name => softMatch(name, 'No Match'))
console.log(matches)
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related