C# 使用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++;

一位朋友问我如何使用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;
   }
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