使用LINQ计算两个字符串之间的匹配字符
一位朋友问我如何用LINQ改进一些代码。 你会如何通过两个字符串之间的字符比较来计算索引的匹配数? 这是原始代码,可以用LINQ进行改进吗?
private int Fitness(string individual, string target) { int sum = 0; for (int i = 0; i < individual.Length; i++) if (individual[i] == target[i]) sum++; return sum; }
return Enumerable.Range(0, individual.Length) .Count(i => individual[i] == target[i]);
一种更加万无一失的方式(如果target
比individual
短,上面的代码片会失败):
return Enumerable.Range(0, Math.Min(individual.Length, target.Length)) .Count(i => individual[i] == target[i]);
我相信代码是正确的。 Enumerable.Range
方法有两个参数。 第一个是起始索引(应为0
),第二个是项目数。 要测试并确保完整的代码段:
class Program { static void Main(string[] args) { Console.WriteLine(Fitness("hello", "world")); } static int Fitness(string individual, string target) { return Enumerable.Range(0, Math.Min(individual.Length, target.Length)) .Count(i => individual[i] == target[i]); } }
您可以使用LINQ编写类似的东西,但由于“Zip”在.NET 4.0之前没有内置,因此代码将超出我们的预期,和/或效率不高。 我很想“按原样”保留它,但我可能会检查target.Length
以避免超出范围的exception。
也许我会做一个扩展方法,但是:
public static int CompareFitness(this string individual, string target) { int sum = 0, len = individual.Length < target.Length ? individual.Length : target.Length; for (int i = 0; i < len; i++) if (individual[i] == target[i]) sum++; return sum; }
然后你可以使用:
string s = "abcd"; int i = s.CompareFitness("adc"); // 2
当前选择的答案不能很好地处理不同长度的字符串。 如果长度不同,它仅比较输入字符串的最大子字符串。
例如:
Fitness("ABC", "ABC") -> 3 Fitness("ABC", "ABC this is an 'unfit' string") -> 3
这可以通过从您的分数中减去不同的长度来轻松解决。 改善:
return Enumerable.Range(0, Math.Min(individual.Length, target.Length)) .Count(i => individual[i] == target[i]) - Math.Abs(individual.Length - target.Length);
现在:
Fitness("ABC", "ABC") -> 3 Fitness("ABC", "ABC this is an 'unfit' string") -> -23
从技术上讲,这两个输入之间有23个字符的差异。
加入怎么样,还是我误解了?
static void Main(string[] args) { var s1 = "abcde"; var s2 = "hycdh"; var count = s1.Join(s2, c => c, c => c, (a,b) => a).Count(); Console.WriteLine(count); Console.ReadKey(); }