Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.87/55: Рейтинг темы: голосов - 55, средняя оценка - 4.87
0 / 0 / 0
Регистрация: 14.05.2012
Сообщений: 19
1

Алгоритм нечеткого сравнения строк

14.05.2012, 21:31. Показов 11542. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет.
В общем мне требуется сравнивать полученные значения в тексбоксе со списком значений из базы данных. В качестве доступного решения нашел алгоритм нечеткого сравнения строк. Нашел реализованный алгоритм на Delphi вот тут http://www.delphikingdom.com/a... alogid=722
ниже представлен переведенный код на C#
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
        
namespace FuzzyCompare
{
    class Fuzzy
    {
        //------------------------------------------------------------------------------
        //MaxMatching - максимальная длина подстроки (достаточно 3-4)
        //strInputMatching - сравниваемая строка
        //strInputStandart - строка-образец
        // Сравнивание без учета регистра
        // if IndistinctMatching(4, "поисковая строка", "оригинальная строка  - эталон") > 40 then ...
        struct RetCount
        {
            public long lngSubRows;
            public long lngCountLike;
        }
        RetCount Matching(string strInputA, string strInputB, int lngLen)
        {
            RetCount TempRet;
            int PosStrA;
            int PosStrB;
            string strTempA;
            string strTempB;
            TempRet.lngCountLike = 0;
            TempRet.lngSubRows = 0;
            for (PosStrA = 0; PosStrA <= strInputA.Length - lngLen; PosStrA++)
            {
                strTempA = strInputA.Substring(PosStrA, lngLen);
                for (PosStrB = 0; PosStrB <= strInputB.Length - lngLen; PosStrB++)
                {
                    strTempB = strInputB.Substring(PosStrB, lngLen);
                    if ((string.Compare(strTempA, strTempB) == 0))
                    {
                        TempRet.lngCountLike = (TempRet.lngCountLike + 1);
                        break;
                    }
                }
                TempRet.lngSubRows = (TempRet.lngSubRows + 1);
            }
            return TempRet;
        }
        public float IndistinctMatching(int MaxMatching, string strInputMatching, string strInputStandart)
        {
            RetCount gret;
            RetCount tret;
            int lngCurLen; //текущая длина подстроки
            //если не передан какой-либо параметр, то выход
            if (MaxMatching == 0 || strInputMatching.Length == 0 || strInputStandart.Length == 0) return 0;
            gret.lngCountLike = 0;
            gret.lngSubRows = 0;
            // Цикл прохода по длине сравниваемой фразы
            for (lngCurLen = 1; lngCurLen <= MaxMatching; lngCurLen++)
            {
                //Сравниваем строку A со строкой B
                tret = Matching(strInputMatching, strInputStandart, lngCurLen);
                gret.lngCountLike = gret.lngCountLike + tret.lngCountLike;
                gret.lngSubRows = gret.lngSubRows + tret.lngSubRows;
                //Сравниваем строку B со строкой A
                tret = Matching(strInputStandart, strInputMatching, lngCurLen);
                gret.lngCountLike = gret.lngCountLike + tret.lngCountLike;
                gret.lngSubRows = gret.lngSubRows + tret.lngSubRows;
            }
            if (gret.lngSubRows == 0) return 0;
            return (float)(gret.lngCountLike * 100.0 / gret.lngSubRows);
        }
 
    }
}
В общем создаю приложение добавляю class Fuzzy ниже прописываю приведенный выше код, на основной форме добавляю 2 texbox'a, label и 2 numericUpDown (подозреваю что это замена SpinEdit'am на Delphi и кнопку button1 ) на обработчик события прописываю
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Windows.Forms;
 
namespace FuzzyCompare
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
 
        public void button1_Click(object sender, EventArgs e)
        {
            int lngMaxLen;
            int lngCase;
            string SFind, SOriginal;
            string Find;
            int i;
            {
                               
                Find = FuzzyCompare.Fuzzy.IndistinctMatching(numericUpDown2.Value, EditFind.Text, EditOriginal.Text);
                label1.Text = Find;
                i = Convert.ToInt32(Find);
                
            }
        }
    }
    
}
в итоге получаю 2 ошибки

Ошибка 2 Аргумент "1": преобразование типа из "decimal" в "int" невозможно ..\FuzzyCompare\FuzzyCompare\Form1.cs 23
Ошибка 1 Наиболее подходящий перегруженный метод для "FuzzyCompare.Fuzzy.IndistinctMatching(int, string, string)" имеет несколько недопустимых аргументов ..\FuzzyCompare\FuzzyCompare\Form1.cs 23
Ниже прикрепил исходник на делфи и исходник с попытками на C# помогите решить задачу.
Вложения
Тип файла: rar FuzzyCompare.rar (39.7 Кб, 32 просмотров)
Тип файла: zip compare.zip (348.4 Кб, 35 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.05.2012, 21:31
Ответы с готовыми решениями:

Алгоритм быстрого сравнения строк
Есть очень много строк.Припустим больше 1000. Есть какой-то способ или алгоритм сравнивать...

Алгоритм сравнения массивов.
Подскажите, плиз. Застрял в программе. Вопрос скорее не по c# а общий по программированию. Задача...

Реализация сравнения строк
Всем доброго времени суток! Сразу оговорюсь программист я начинающий. Задача: Имеются два файла...

Помогите исправить ошибку сравнения строк
В общем помогите исправить ошибки и запустить программу, разобраться не могу как правильно описать:...

5
660 / 530 / 137
Регистрация: 07.07.2011
Сообщений: 1,232
14.05.2012, 21:50 2
Вот исправил, но меня смущает данный алгоритм...
Вложения
Тип файла: rar FuzzyCompare.rar (41.6 Кб, 141 просмотров)
1
0 / 0 / 0
Регистрация: 14.05.2012
Сообщений: 19
14.05.2012, 22:02  [ТС] 3
Цитата Сообщение от Дмитрий3241 Посмотреть сообщение
Вот исправил, но меня смущает данный алгоритм...
благодарю чем вызвано ваше смущение?
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
14.05.2012, 22:30 4
вот тут есть полноценный код для нечеткого сравнения, там даже процент похожести выводится
http://www.codeproject.com/Art... etween-str

кроме него я еще юзаю такой вариант
развернуть
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    public class StringSimilarComparer : IEqualityComparer<string>
    {
        public bool Equals(string x, string y)
        {
            return AreSimilar(x, y);
        }
 
        public int GetHashCode(string obj)
        {
            return obj.GetHashCode();
        }
 
        public static bool AreSimilar(string s1, string s2)
        {
            if (s1 == null) return false;// throw new ArgumentNullException("s1");
            if (s2 == null) return false;//throw new ArgumentNullException("s2");
 
            if (s1 == String.Empty || s2 == string.Empty)
                return false;
 
            StringBuilder strMax, strMin;
            if (s1.Length >= s2.Length)
            {
                strMax = new StringBuilder(s1);
                strMin = new StringBuilder(s2);
            }
            else
            {
                strMax = new StringBuilder(s2);
                strMin = new StringBuilder(s1);
            }
 
            int ind1, ind2;
            var lastSub = LongestCommonSubstring(strMax, strMin, out ind1, out ind2);
 
            if (lastSub <= 0) //вообще нет ничего общего
                return false;
 
            if (lastSub >= strMin.Length)
                return true;//наименьшая строка полностью входит в наибольшую, либо равна ей
 
            const int strong = 1;
            const int strong2 = 1;
 
            int length = 0;
 
            do
            {
                length += lastSub;
                strMax.Remove(ind1, lastSub);
                strMin.Remove(ind2, lastSub);
                lastSub = LongestCommonSubstring(strMax, strMin, out ind1, out ind2);
 
            } while ((lastSub >= 2 + strong ) || (lastSub > 0 && char.IsDigit(strMax[ind1])));
 
 
            int length1 = s1.Length;
            int length2 = s2.Length;
 
            int min1 = (int)(length1 * 0.20f); //20% от общей длины строки
            int min2 = (int)(length2 * 0.20f);
 
            return ((length1 - min1 + strong <= length) || (length2 - min2 + strong <= length));
        }
 
        private static int LongestCommonSubstring(StringBuilder str1, StringBuilder str2, out int str1Offset, out int str2Offset)
        {
            if (str1 == null) throw new ArgumentNullException("str1");
            if (str2 == null) throw new ArgumentNullException("str2");
 
 
            if (str1.Length <= 0 || str2.Length <= 0)
            {
                str1Offset = -1;
                str2Offset = -1;
                return 0;
            }
 
            int[,] num = new int[str1.Length, str2.Length];
 
            int maxlen = 0;
            int saveIndexI = 0;
            int saveIndexJ = 0;
 
            for (int i = 0; i < str1.Length; i++)
            {
                for (int j = 0; j < str2.Length; j++)
                {
                    if (char.ToLower(str1[i]) != char.ToLower(str2[j]))
                    {
                        num[i, j] = 0;
                    }
                    else
                    {
                        if ((i == 0) || (j == 0))
                        {
                            num[i, j] = 1;
                        }
                        else
                        {
                            num[i, j] = 1 + num[i - 1, j - 1];
                        }
 
                        if (num[i, j] > maxlen)
                        {
                            maxlen = num[i, j];
                            saveIndexI = i;
                            saveIndexJ = j;
                        }
                    }
                }
            }
 
            str1Offset = saveIndexI - maxlen + 1;
            str2Offset = saveIndexJ - maxlen + 1;
 
            return maxlen;
        }
    }

там есть пара своих тараканов, под свои цели затачивал долго и со вкусом )
1
660 / 530 / 137
Регистрация: 07.07.2011
Сообщений: 1,232
14.05.2012, 22:31 5
Уже не чем, пересмотрел проект на Delphi, отстранился от идеи.
0
0 / 0 / 0
Регистрация: 14.05.2012
Сообщений: 19
15.05.2012, 00:01  [ТС] 6
Цитата Сообщение от m0nax Посмотреть сообщение
вот тут есть полноценный код для нечеткого сравнения, там даже процент похожести выводится
http://www.codeproject.com/Art... etween-str

кроме него я еще юзаю такой вариант
развернуть
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    public class StringSimilarComparer : IEqualityComparer<string>
    {
        public bool Equals(string x, string y)
        {
            return AreSimilar(x, y);
        }
 
        public int GetHashCode(string obj)
        {
            return obj.GetHashCode();
        }
 
        public static bool AreSimilar(string s1, string s2)
        {
            if (s1 == null) return false;// throw new ArgumentNullException("s1");
            if (s2 == null) return false;//throw new ArgumentNullException("s2");
 
            if (s1 == String.Empty || s2 == string.Empty)
                return false;
 
            StringBuilder strMax, strMin;
            if (s1.Length >= s2.Length)
            {
                strMax = new StringBuilder(s1);
                strMin = new StringBuilder(s2);
            }
            else
            {
                strMax = new StringBuilder(s2);
                strMin = new StringBuilder(s1);
            }
 
            int ind1, ind2;
            var lastSub = LongestCommonSubstring(strMax, strMin, out ind1, out ind2);
 
            if (lastSub <= 0) //вообще нет ничего общего
                return false;
 
            if (lastSub >= strMin.Length)
                return true;//наименьшая строка полностью входит в наибольшую, либо равна ей
 
            const int strong = 1;
            const int strong2 = 1;
 
            int length = 0;
 
            do
            {
                length += lastSub;
                strMax.Remove(ind1, lastSub);
                strMin.Remove(ind2, lastSub);
                lastSub = LongestCommonSubstring(strMax, strMin, out ind1, out ind2);
 
            } while ((lastSub >= 2 + strong ) || (lastSub > 0 && char.IsDigit(strMax[ind1])));
 
 
            int length1 = s1.Length;
            int length2 = s2.Length;
 
            int min1 = (int)(length1 * 0.20f); //20% от общей длины строки
            int min2 = (int)(length2 * 0.20f);
 
            return ((length1 - min1 + strong <= length) || (length2 - min2 + strong <= length));
        }
 
        private static int LongestCommonSubstring(StringBuilder str1, StringBuilder str2, out int str1Offset, out int str2Offset)
        {
            if (str1 == null) throw new ArgumentNullException("str1");
            if (str2 == null) throw new ArgumentNullException("str2");
 
 
            if (str1.Length <= 0 || str2.Length <= 0)
            {
                str1Offset = -1;
                str2Offset = -1;
                return 0;
            }
 
            int[,] num = new int[str1.Length, str2.Length];
 
            int maxlen = 0;
            int saveIndexI = 0;
            int saveIndexJ = 0;
 
            for (int i = 0; i < str1.Length; i++)
            {
                for (int j = 0; j < str2.Length; j++)
                {
                    if (char.ToLower(str1[i]) != char.ToLower(str2[j]))
                    {
                        num[i, j] = 0;
                    }
                    else
                    {
                        if ((i == 0) || (j == 0))
                        {
                            num[i, j] = 1;
                        }
                        else
                        {
                            num[i, j] = 1 + num[i - 1, j - 1];
                        }
 
                        if (num[i, j] > maxlen)
                        {
                            maxlen = num[i, j];
                            saveIndexI = i;
                            saveIndexJ = j;
                        }
                    }
                }
            }
 
            str1Offset = saveIndexI - maxlen + 1;
            str2Offset = saveIndexJ - maxlen + 1;
 
            return maxlen;
        }
    }

там есть пара своих тараканов, под свои цели затачивал долго и со вкусом )
спасибо=) быть может пригодится просто в у меня 2 строка будет достоверно точной планирую подцепить её из listbox'a а на входе у меня символы из распознанного изображения выводятся в textboxну и нужно сравнить распознанные значения со значениями из таблицы из базы данных буду пытаться реализовать на c# как то тяжеловато
0
15.05.2012, 00:01
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.05.2012, 00:01
Помогаю со студенческими работами здесь

Реализовать метод CompareTo для сравнения строк
Задание такое: В класс Edition добавить реализацию интерфейсa System.IComparable для сравнения...

Остановить цикл сравнения строк при их совпадении
мне надо чтобы цикл останавливался а не начинался с нуля! int k = 6; ...

Алгоритм сравнения версий в формате "х.х.х"
Добрый день! У меня есть список(List&lt;string&gt;) с версиями: &quot;0.9.6&quot; &quot;0.9.5&quot; Нужно оттуда достать...

Многокритериальный выбор компаний на основе нечеткого выбора
Добрый день господа! у меня такая задача, есть некоторые критерии = альтернативы их порядком штук...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru