Skip to content

Commit 5e41955

Browse files
committed
resolved #194
1 parent 3598561 commit 5e41955

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

src/CatLib.Core.Tests/Support/Util/StrTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
using System;
13+
using System.Text;
1314
using System.Text.RegularExpressions;
1415
using CatLib.Tests;
1516
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -346,5 +347,25 @@ public void TestIsArr()
346347
Assert.AreEqual("CatLib.ILRuntime", result[1]);
347348
Assert.AreEqual("CatLib.Route", result[2]);
348349
}
350+
351+
[TestMethod]
352+
public void TestLevenshtein()
353+
{
354+
Assert.AreEqual(4, Str.Levenshtein("hello", "world"));
355+
Assert.AreEqual(5, Str.Levenshtein("hello", "catlib"));
356+
}
357+
358+
[TestMethod]
359+
public void TestLevenshteinLargeThan255()
360+
{
361+
var builder = new StringBuilder(256);
362+
for (var i = 0; i < 256; i++)
363+
{
364+
builder.Append('a');
365+
}
366+
367+
Assert.AreEqual(256, builder.Length);
368+
Assert.AreEqual(-1, Str.Levenshtein(builder.ToString(), "world"));
369+
}
349370
}
350371
}

src/CatLib.Core/Support/Util/Str.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,66 @@ public static string Truncate(string str, int length, object separator = null, s
491491

492492
return result + mission;
493493
}
494+
495+
/// <summary>
496+
/// 计算两个字符串之间的相似度。
497+
/// </summary>
498+
/// <param name="str1">字符串 1.</param>
499+
/// <param name="str2">字符串 2.</param>
500+
/// <returns>
501+
/// 通过Levenshtein算法返回两个字符串的相似度。如果两个字符串之间的
502+
/// 任意一个参数长度大于255那么。将会返回-1。
503+
/// </returns>
504+
public static int Levenshtein(string str1, string str2)
505+
{
506+
var length1 = str1.Length;
507+
var length2 = str2.Length;
508+
509+
if (length1 > 255 || length2 > 255)
510+
{
511+
return -1;
512+
}
513+
514+
var p1 = new int[length2 + 1];
515+
var p2 = new int[length1 + 1];
516+
517+
for (var i = 0; i <= length2; i++)
518+
{
519+
p1[i] = i;
520+
}
521+
522+
int Min(int num1, int num2, int num3)
523+
{
524+
var min = num1;
525+
if (min > num2)
526+
{
527+
min = num2;
528+
}
529+
if (min > num3)
530+
{
531+
min = num3;
532+
}
533+
return min;
534+
}
535+
536+
for (var i = 0; i < length1; i++)
537+
{
538+
p2[0] = p1[0] + 1;
539+
for (var n = 0; n < length2; n++)
540+
{
541+
var distance = str1[i] == str2[n]
542+
? Min(p1[n], p1[n + 1] + 1, p2[n] + 1)
543+
: Min(p1[n] + 1, p1[n + 1] + 1, p2[n] + 1);
544+
p2[n + 1] = distance;
545+
}
546+
547+
var temp = p1;
548+
p1 = p2;
549+
p2 = temp;
550+
}
551+
552+
return p1[length2];
553+
}
494554
}
495555
}
496556

0 commit comments

Comments
 (0)