Esempio n. 1
0
        /// <summary>
        /// Расстояние Джаро—Винклера между двумя последовательностями символов. Чем меньше
        /// расстояние, тем больше сходства имеют эти строки друг с другом.
        /// </summary>
        /// <param name="string1">Первая строка.</param>
        /// <param name="string2">Вторая строка.</param>
        /// <param name="settings">Настройки сравнения.</param>
        /// <returns>
        /// Метод возвращает нормированный результат, так что 0 означает отсутствия сходства,
        /// а 1 - точное совпадение.
        /// </returns>
        /// <remarks>
        /// Сравнение строк чувствительно к регистру символов.
        /// </remarks>
        public static double JaroWinklerDistance(string string1, string string2, IStringComparisonSettings settings)
        {
            var jaroDistance = JaroDistance(string1, string2, settings);

            if (jaroDistance <= JARO_WINKLER_WEIGHT_THRESHOLD)
            {
                return(jaroDistance);
            }
            var max = Math.Min(JARO_WINKLER_NUM_CHARS, Math.Min(string1.Length, string2.Length));
            var pos = 0;

            while (pos < max && string1[pos] == string2[pos])
            {
                ++pos;
            }
            if (pos == 0)
            {
                return(jaroDistance);
            }
            return(jaroDistance + 0.1 * pos * (1.0 - jaroDistance));
        }
Esempio n. 2
0
        /// <summary>
        /// Расстояние Джаро между двумя последовательностями символов. Чем меньше
        /// расстояние, тем больше сходства имеют эти строки друг с другом.
        /// </summary>
        /// <param name="string1">Первая строка.</param>
        /// <param name="string2">Вторая строка.</param>
        /// <param name="settings">Настройки сравнения.</param>
        /// <returns>
        /// Метод возвращает нормированный результат, так что 0 означает отсутствия сходства,
        /// а 1 - точное совпадение.
        /// </returns>
        /// <remarks>
        /// Сравнение строк чувствительно к регистру символов.
        /// </remarks>
        public static double JaroDistance(string string1, string string2, IStringComparisonSettings settings)
        {
            if (settings == null)
            {
                settings = new StringComparisonSettings();
            }

            var len1 = string1.Length;
            var len2 = string2.Length;

            if (len1 == 0)
            {
                return(len2 == 0 ? 1.0 : 0.0);
            }
            if (len2 == 0)
            {
                return(0.0);
            }

            if (!settings.AccentSensitive)
            {
                string1 = string1.Replace("ё", "е");
                string1 = string1.Replace("Ё", "Е");
                string2 = string2.Replace("ё", "е");
                string2 = string2.Replace("Ё", "Е");
            }
            if (!settings.CaseSensitive)
            {
                string1 = string1.ToUpper();
                string2 = string2.ToUpper();
            }

            var searchRange = Math.Max(0, Math.Max(len1, len2) / 2 - 1);

            var matched1 = new bool[len1];
            var matched2 = new bool[len2];

            var numCommon = 0;

            for (var i = 0; i < len1; ++i)
            {
                var start = Math.Max(0, i - searchRange);
                var end   = Math.Min(i + searchRange + 1, len2);
                for (var j = start; j < end; ++j)
                {
                    if (matched2[j])
                    {
                        continue;
                    }
                    if (string1[i] != string2[j])
                    {
                        continue;
                    }
                    matched1[i] = true;
                    matched2[j] = true;
                    ++numCommon;
                    break;
                }
            }
            if (numCommon == 0)
            {
                return(0.0);
            }

            var numHalfTransposed = 0;
            var k = 0;

            for (var i = 0; i < len1; ++i)
            {
                if (!matched1[i])
                {
                    continue;
                }
                while (!matched2[k])
                {
                    ++k;
                }
                if (string1[i] != string2[k])
                {
                    ++numHalfTransposed;
                }
                ++k;
            }
            var    numTransposed = numHalfTransposed / 2;
            double numCommonD    = numCommon;

            return((numCommonD / len1 + numCommonD / len2 + (numCommon - numTransposed) / numCommonD) / 3.0);
        }