C# 使用LINQ对两个字符串之间的匹配字符进行计数
一位朋友问我如何使用LINQ改进一些代码。如何在两个字符串之间进行逐字符比较,以计算索引中的匹配数?这是原始代码,可以用LINQ改进吗C# 使用LINQ对两个字符串之间的匹配字符进行计数,c#,linq,C#,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++;
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;
}
private int Fitness(字符串个体,字符串目标)
{
整数和=0;
for(int i=0;i
更简单的方法是(如果target
比individual
短,则上述代码段将失败):
我相信代码是正确的。方法接受两个参数。第一个是开始索引(应该是
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”直到.NET4.0才内置,因此它的代码比我们希望的要多,并且/或者没有我们希望的那么高效。我很想让它保持“原样”,但我可能会检查target.Length
,以避免出现超出范围的异常
不过,也许我会做一个扩展方法:
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;
}
加入怎么样,还是我误解了
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();
}
当前选择的答案不能很好地处理不同长度的字符串。如果长度不同,它只比较输入字符串的最大子字符串 例如:
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);
现在:
从技术上讲,这两个输入之间有23个字符的差异。同意长度检查。这和Zip有什么关系?Zip需要两个序列并将它们逐项组合在一起…?同意,Marc,但我接受Mehrdad的答案,因为我想看看这在LINQ中是如何实现的。我也投票赞成你的答案。谢谢我明白,但是在这种情况下,
Zip
如何减少代码大小(相对于我的答案)?至少对于支持通过索引直接访问的集合来说,它在代码大小上不会有太大的差别。我手头没有4.0版本的Zip,但它不是类似于individual.Zip(target.Count)(pair=>pair.X==pair.Y)代码>-但重要的是,我们没有弄乱Min(即,这取代了您的第二个版本),现在比较“ababa”和“babab”-应该是零,但返回12-帕沃。我想把它作为zip和join之间差异的一个例子。由于数组是零基的,Range
的第二个参数是count,而不是最后一项。这就是为什么需要使用Length-1。当您计算单个[Indicate.Length]时,将得到一个“索引超出范围异常”。e、 g.如果数组长度为1,那么唯一的元素是foo[0],foo[1]不存在。@Kirk:正如我所说的,这是正确的,因为Enumerable.Range
需要的是计数,而不是长度。它从不尝试计算individual[individual.Length]
。你是真的测试了代码还是只是猜测?当我测试时,我得到的索引超出了范围,除非我使用了Length-1
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();
}
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