2013-05-08 3 views
0

Что является самым простым способом, с наименьшим количеством кода, для сравнения двух строк, игнорируя при этом следующее:равенство двух строк

"hello world" == "hello world"     // spaces 
"hello-world" == "hello world"     // hyphens 
"Hello World" == "hello worlD"     // case 
"St pierre" == "saint pierre" == "St. Pierre" // word replacement 

Я уверен, что это было сделано раньше, и есть некоторые библиотеки делают такие вещи, но я не знаю. Это предпочтительно на C++, но если на любом другом языке есть очень короткий вариант, я тоже хочу услышать об этом.

Альтернативно, меня также интересовала бы любая библиотека, которая могла бы дать процент соответствия. Скажем, hello-world и hello wolrd 97%, вероятно, будут иметь то же значение, просто дефис и неправильное обращение.

+2

Слишком много случаев здесь .. вам нужно выяснить, что вы хотите, и все правила. – 2013-05-08 17:09:49

+3

Я думаю, что вы вопрос слишком широк. Если у вас есть конкретные проблемы с вашей реализацией, мы можем помочь с этим, но, поскольку это стоит, вы в основном просите сообщество SO написать всю вашу программу для вас. – Chris

+0

«Слово Замена» - это то, что пишет книги, а не абзац. –

ответ

2
  1. Удалите пробелы из обеих строк.
  2. Удалить дефисы из обеих строк.
  3. Преобразуйте обе строки в нижний регистр.
  4. Преобразуйте все вхождения «святого» и «st.» В «st».
  5. Сравните строки, как обычно.

Например:

#include <cctype> 
#include <string> 
#include <algorithm> 
#include <iostream> 

static void remove_spaces_and_hyphens(std::string &s) 
{ 
    s.erase(std::remove_if(s.begin(), s.end(), [](char c) { 
       return c == ' ' || c == '-'; 
      }), s.end()); 
} 

static void convert_to_lower_case(std::string &s) 
{ 
    for (auto &c : s) 
     c = std::tolower(c); 
} 

static void 
replace_word(std::string &s, const std::string &from, const std::string &to) 
{ 
    size_t pos = 0; 
    while ((pos = s.find(from, pos)) != std::string::npos) { 
     s.replace(pos, from.size(), to); 
     pos += to.size(); 
    } 
} 

static void replace_words(std::string &s) 
{ 
    replace_word(s, "saint", "st"); 
    replace_word(s, "st.", "st"); 
} 

int main() 
{ 
    // Given two strings: 
    std::string s1 = "Hello, Saint Pierre!"; 
    std::string s2 = "hELlO,St.PiERRe!"; 

    // Remove spaces and hyphens. 
    remove_spaces_and_hyphens(s1); 
    remove_spaces_and_hyphens(s2); 

    // Convert to lower case. 
    convert_to_lower_case(s1); 
    convert_to_lower_case(s2); 

    // Replace words... 
    replace_words(s1); 
    replace_words(s2); 

    // Compare. 
    std::cout << (s1 == s2 ? "Equal" : "Doesn't look like equal") << std::endl; 
} 

Существует способ, конечно, более эффективного кодирования, но я рекомендую вам начать с чем-то работы и оптимизировать его только тогда, когда она оказывается узким местом.

Возможно, вас заинтересует string similarity algorithms как “Levenshtein distance”. Подобные алгоритмы используются, например, поисковой системой или редакторами для предложения предложений о коррекции заклинаний.

+1

Работает в конкретном случае, но более точный алгоритм должен быть «заменять любую последовательность», \ t, \ n с одним «», а не «удалять все пробелы». Если вы удалите их все, вы можете сопоставить то, что требуется, чтобы оставаться отличным. –

0

QRegExp - это то, что вы ищете. Он не будет распечатывать проценты, но вы можете сделать несколько хороших способов сравнения одной строки с другой и найти количество совпадений одной строки с другой.

Регулярные выражения доступны с почти всегда языком. Мне нравится GSkinner's RegEx страница для изучения регулярных выражений.

http://qt-project.org/doc/qt-4.8/qregexp.html

Надежда, что помогает.

1

Я не знаю ни одной библиотеки, но для эквализации, если скорость не является rpoblem, вы можете выполнять char-by-char сравнивать и игнорировать «специальные» символы (соответственно перемещать итератор далее в тексте).

Что касается сравнения текстов, вы можете использовать простые Levenshtein distance.

1

Для пробелов и дефисов просто замените все пробелы/дефисы в строке и выполните сравнение. Для случая конвертируйте весь текст в верхний или нижний регистр и выполните сравнение. Для замены слова вам понадобится словарь слов, ключ которого является аббревиатурой, а значение является заменяющим словом. Вы также можете рассмотреть алгоритм Levenshtein Distance, показывающий, как одна подобная фраза относится к другой. Если вам нужна статистическая вероятность того, насколько близко слово/фраза относится к другому слову/фразе, вам понадобятся образцы данных для сравнения.

0

в течение первых 3 ТРЕБОВАНИЙ,

  1. демонтировать все пространства/hypens из строки (или заменить его на голец, например, '') "привет мир" -> "привет мир"
  2. сравнить их игнорировать корпус. Case insensitive string comparison in C++

для последней просьбы, это более уместно.
Сначала вам нужен словарь, который в KV-структуре:
'St.': 'saint'
'Mr.«:„Господин“

второго маркера использовать импульс для того чтобы отделить строку, и приведите затем в КВ-магазине
замените маркер на строку, но она может в низкой производительности:

http://www.boost.org/doc/libs/1_53_0/libs/tokenizer/tokenizer.htm

+1

Удаление символов будет медленнее, чем повторение символа char-by-char и сравнение символов по отношению к игнорируемым символам. –

+0

Вы правы, удаление символов неэффективно. –

Смежные вопросы