Как сопоставить две строки по последовательности слов в javascript? - PullRequest
0 голосов
/ 27 апреля 2020

Нужно найти строку, которая больше всего соответствует данной строке.

list = ['Mr. Adam Smith Junior', 'Anna Smith Jr.', 'Adam Jhon Smith', 'Smith Adam'];
str = 'Adam Smith Jr.';

// output: 'Mr. Adam Smith Junior'

Я пробовал путем токенизации слов, и для каждого элемента в списке он совпадает с 2 токенами (Адам / Смит / младший .). Но мой ожидаемый результат - список [0]. Поэтому мне нужно решение, чтобы найти соответствующую строку по наиболее подходящей последовательности слов.

Ответы [ 3 ]

0 голосов
/ 27 апреля 2020

Предполагая:

  • порядок соответствия str имеет значение,
  • вы хотите элемент в списке, который соответствует самой длинной части поискового слова,
  • и элемент, наиболее соответствующий началу str;

эта функция должна сделать это:

    var list = ['Mr. Adam Smith Junior', 'Anna Smith Jr.', 'Adam Jhon Smith', 'Smith Adam'];
    var str = 'Adam Smith Jr.';

    function onlyUnique(value, index, self) {
        // See: https://stackoverflow.com/a/14438954/2142071
        return self.indexOf(value) === index;
    }

    function getBestMatch(word, list, minimal_length) {
        // Minimal length is used to make the search more meaningful;
        // single character searches would not be helpful most of the times
        if ( word.length < minimal_length ) {
            return ['', -1]; // None found, word is too short
        }

        // Pre-process search RegEx patterns
        var patterns = [];
        var words = [];
        // For all possible starting positions inside `word`:
        // So:
        // Adam Smith Jr.
        // dam Smith Jr.
        // am Smith Jr.
        // .. etc ..
        for (var i = 0; i <= word.length - minimal_length; i++) {
            var temp_word = word.substring(i);
            // For every part of the remainder of `word`:
            // So:
            // Adam Smith Jr.
            // Adam Smith Jr
            // Adam Smith J
            // .. etc ..
            for (var j = minimal_length; j <= temp_word.length; j++) {
                // Add that word part to a central array of patterns to search for in list
                var word_part = temp_word.substring(0, j);
                words[ words.length ] = word_part;
            }
        }
        
        // Sort all unique word parts
        words = words.filter( onlyUnique );
        words.sort(function(a, b){
            // (longest parts first, since they are assumed a better match)
            return b.length - a.length;
        });

        // For every word part:
        for (var i = 0; i < words.length; i++) {
            // Create RegEx pattern
            var pattern = new RegExp( words[ i ] );
            
            // Search each item in the list using this pattern for a match.
            for (var n = 0; n < list.length; n++) {
                if ( words[ i ].length <= list[ n ].length ) {
                    if ( pattern.test( list[ n ] ) ) {
                        // Return the first match and its index
                        return [list[ n ], n];
                    }
                }
            }
        }

        return ['', -1]; // None found
    }

    var match = getBestMatch(str, list, 2);
    // match[0] is the matched item
    // match[1] is the index of that item in the list
    console.log( match[0], 'at index', match[1] );

Примечание: Имейте в виду сложность, которую уже имеет эта функция без учета таких проблем, как:

  • Должно ли слово в str соответствовать в целом?
  • Могут ли совпадения частей в str быть в другом порядке?
  • А как насчет слов с ошибками?
  • .. et c ..
  • А какой счет / значение следует отнести к совпадению (например, Что определяет «лучшее» совпадение?)
  • Должно ли оно вернуть все совпадения с лучший результат или только один? (А какой?)
  • Производительность: сколько возможных частей слова нужно сгенерировать и поиск (для каждого элемента в list)

Следовательно , поиск - это собственное программирование. ;)

0 голосов
/ 27 апреля 2020
// Your code request - Updated code.
var list = ['Mr. Adam Smith Junior', 'Anna Smith Jr.', 'Adam Jhon Smith', 'Smith Adam'];
var str = 'Adam Smith Jr.';

// Updated code.
str = str.split(' ');
var i = 0, j = 0;
var matched = [];

// First loop for your `list` variable array to go through each string.
while(i < str.length){
    // Second loop for your `str` variable to match each part of string with your `list` variable's each string.    
    for(j=0;j < list.length;j++){      
        var match = new RegExp( str[i], 'g' );  
            if(list[j].match(match)){
            // Find exact match - Your code goes here.
            if(!matched.includes(list[j])){
                matched.push(list[j]);
            }

          }
        }
  i++;
}

// Your result of find the all matched values from `list` variable.
console.log(matched);
0 голосов
/ 27 апреля 2020

Мне было интересно, если вы ищете что-то вроде этого:

var list = ['Mr. Adam Smith Junior', 'Anna Smith Jr.', 'Adam Jhon Smith', 'Smith Adam'];
var str = 'Adam Smith Jr.';

// This loop finds the best matching string in the array and
// and prints it in the console
function findBestMatch(arr, s) {
    for (var i = s.length; i > 1; i--) {
        var found = arr.find(function(ele) {
            return ele.indexOf(s.substr(0, i)) > -1;
        }) || [];
        if (found.length) {
            console.info(found);
            break;
        }
    }
}

findBestMatch(list, str);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...