Как сравнить 2 строки с int из ошибок? - PullRequest
1 голос
/ 17 марта 2011

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

У меня есть форма с 2-мя текстовыми полями (одно поверх другого) и 2 кнопками. Верхнее поле - это основной текст (строка), а нижнее поле - текст записи (строка). Каждый участник отправляет текст в учетную запись электронной почты, из электронного письма мы копируем и вставляем текст в RTB Entry и сравниваем с Master RTB. Для каждого отдельного слова и одного пробела считается вещь для проверки. Слово, независимо от того, сколько ошибок оно имеет, все равно 1 ошибка. И за каждую ошибку добавьте 1 сек. к своему времени.

Примеры:

  • Привет! <= 3 проверки (2 слова и 1 пробел) <br>
    • Helothere! <= 2 ошибки (Helo и пробел) </li>
    • Привет! <= 1 ошибка (дополнительно! В конце там!) </li>
  • Привет! Как твои дела?
    • Helothere !! Как твои дела? <= еще 9 проверок, 4 ошибки (helo, без пробела, лишние! и пробел в) </li>
    • Привет! @ Как ты? <= 3 ошибки (@ в конце там! Нет w, no o и extra? (Все ошибки все еще находятся под 1 словом) </li>

Что у меня так далеко: Я создал 6 массивов (3 для мастера, 3 для входа), и они

  • CharArray всех символов
  • StringArray всех строк (слов), включая пробелы
  • IntArray с длиной строки в каждом StringArray

Моя самая большая проблема в том, что текст ввода неправильный и он короче или длиннее, чем основной. Я продолжаю получать исключения IndexOutOfRange (понятно), но не могу понять, как выполнить проверку и написание кода для компенсации. Надеюсь, я достаточно ясно дал понять, в чем мне нужна помощь. Если бы кто-нибудь мог привести несколько примеров кода или что-то, что могло бы застрелить меня по правильному пути, было бы очень полезно.

Ответы [ 4 ]

2 голосов
/ 17 марта 2011

Вы изучили алгоритм расстояния Левенштейна ?Он возвращает количество различий между двумя строками, которые, в вашем случае, будут текстовыми ошибками.Реализация алгоритма, основанного на псевдокоде, найденном на странице википедии, пропускает первые 3 из ваших 4 вариантов использования:

Assert.AreEqual(2, LevenshteinDistance("Hello there!", "Helothere!");
Assert.AreEqual(1, LevenshteinDistance("Hello there!", "Hello there!!"));

Assert.AreEqual(4, LevenshteinDistance("Hello there! How are you?", "Helothere!! How a re you?"));
Assert.AreEqual(3, LevenshteinDistance("Hello there! How are you?", "Hello there!@ Ho are yu??"));  //fails, returns 4 errors

Так что, хотя и не идеальный из коробки, он, вероятно, является хорошей отправной точкой длявы.Кроме того, если у вас слишком много проблем с реализацией ваших правил оценки, возможно, стоит пересмотреть их.

hth

Обновление:

Вот результат запрошенной вами строкив комментариях:

Assert.AreEqual(7, LevenshteinDistance("Hello there! How are you?", "Hlothere!! Hw a reYou?");  //fails, returns 8 errors

А вот моя реализация алгоритма расстояния Левенштейна:

int LevenshteinDistance(string left, string right)
{
    if (left == null || right == null)
    {
        return -1;
    }

    if (left.Length == 0)
    {
        return right.Length;
    }

    if (right.Length == 0)
    {
        return left.Length;
    }

    int[,] distance = new int[left.Length + 1, right.Length + 1];

    for (int i = 0; i <= left.Length; i++)
    {
        distance[i, 0] = i;
    }

    for (int j = 0; j <= right.Length; j++)
    {
        distance[0, j] = j;
    }

    for (int i = 1; i <= left.Length; i++)
    {
        for (int j = 1; j <= right.Length; j++)
        {
            if (right[j - 1] == left[i - 1])
            {
                distance[i, j] = distance[i - 1, j - 1];
            }
            else
            {
                distance[i, j] = Min(distance[i - 1, j] + 1,      //deletion
                                     distance[i, j - 1] + 1,      //insertion
                                     distance[i - 1, j - 1] + 1); //substitution
            }
        }
    }

    return distance[left.Length, right.Length];
}

int Min(int val1, int val2, int val3)
{
    return Math.Min(val1, Math.Min(val2, val3));
}
0 голосов
/ 17 марта 2011

Я однажды реализовал алгоритм (который я не могу найти в данный момент, я опубликую код, когда я его найду), который проверял общее количество ПАР в целевой строке. Т.е. "Привет, мир!" будет иметь 11 пар, {"He", "el", "ll", ..., "ld", "d!" }.

Затем вы делаете то же самое для входной строки, такой как "Helo World", поэтому у вас есть {"He", ..., "ld"}.

Затем можно вычислить точность как функцию правильных пар (т. Е. Входных пар, которые есть в списке целевых пар), неправильных пар (т. Е. Входных пар, которых нет в списке целевых пар), по сравнению с общим список целевых пар. При достаточно длинных предложениях эта мера будет очень точной справедливой.

0 голосов
/ 17 марта 2011

Вам нужно придумать систему оценки, которая подходит для вашей ситуации.

Я бы сделал массив слов после каждого пробела.

  • Если слово найдено в том же индексе + 5.
  • Если слово найдено в том же индексе + -1 положение индекса +3 (держите счетчик, сколько словотличаются, чтобы увеличить + - исправление
  • Если нужное слово найдено как часть другого слова + 2

и т. д. Совпадение слов затруднительно, работа с механизмом правилэто работает "проще"

0 голосов
/ 17 марта 2011

Простой алгоритм - проверять букву за буквой.Если буквы отличаются, увеличивайте количество ошибок.Если следующая пара букв совпадает, это переключаемая буква, поэтому просто продолжайте.Если сообщение соответствует следующей букве, это упущение и относиться к нему соответственно.Если следующая буква соответствует испорченной, вставьте ее и обработайте соответственно.В противном случае человек действительно испортился и продолжает.

Это не все, но с несколькими изменениями это может стать всеобъемлющим.

слабая попытка псевдокода: правка: новая идея.посмотрите на комментарии.Я не знаю, как работают струны на моей голове, так что вам придется разобраться с этой частью.Алгоритм не работает для слов, которые многократно повторяются, хотя ...

string entry; //we'll pretend that this has stuff inside
string master; // this too...
string tempentry = entry; //stuff will be deleted so I need a copy to mess up
int e =0; //word index for entry
int m = 0; //word index for master
int errors = 0;
while(there are words in tempentry) //!tempentry.empty() ?
  string mword = the next word in master;
  m++;
  int eplace = find mword in tempentry; //eplace is the index of where the mword starts in tempentry
  if(eplace == -1) //word not there...
    continue;
  else
     errors += m - e;
     errors += find number of spaces before eplace
     e = m // there is an error
     tempentry = stripoff everything between the beginning and the next word// substring?
all words and spaces left in master are considered errors.

Есть несколько ошибок проверки границ, которые необходимо исправить здесь, но это хорошее начало.

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