Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#Linq如何比较两个字符串并报告第一个不同的字符,它本身不同于'';通配符_C#_Linq - Fatal编程技术网

C#Linq如何比较两个字符串并报告第一个不同的字符,它本身不同于'';通配符

C#Linq如何比较两个字符串并报告第一个不同的字符,它本身不同于'';通配符,c#,linq,C#,Linq,我有一个比较两个字符串并报告第一个不同字符的函数: public static int Diff(this string str1, string str2) { try { if (str1 == null || str2 == null) return 0; int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();

我有一个比较两个字符串并报告第一个不同字符的函数:

public static int Diff(this string str1, string str2)
{
    try
    {
        if (str1 == null || str2 == null)
            return 0;
        int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
        return index;
    }
    catch (Exception)
    {
        return 0;
    }

}
所有的魔力都在这里:

int index = str1.Zip(str2, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
假设我们有两个字符串:

输入,1,1,0,0,0,0,0,0,0,0,0,0

输入、、、1、、、、、、、、、、、、、

01234567890

那么,考虑到所有的字符,第一个不同的是?所以答案是6(从0开始)。这很有效

现在我想介绍一下?作为通配符字符,因此必须跳过,因此答案应为10(从0开始)

我不知道如何更改上面linq表达式中的代码来实现这一点。 我尝试了
intindex=str1.Zip(str2,(c1,c2)=>c1==c2&&c2!='?')。TakeWhile(b=>b.Count()但这不会改变任何事情,并且总是报告6而不是9

我想坚持使用linq,而不是通过(更简单的)for循环
谢谢

我想你只需要稍微改变一下逻辑条件

如果
Zip
中使用的条件为假,我们将停止查找。只有当两个字符不相同且其中一个不是通配符时,我们才应该停止查找

因此,条件应该是:

!(c1 != c2 && (c1 != '?' || c2 != '?'))
显然,这可以用德摩根定律来简化:

c1 == c2 || c1 != '?' || c2 != '?'
因此,该行变为:

index = str1.Zip(str2, (c1, c2) => c1 == c2 || c1 != '?' || c2 != '?').TakeWhile(b => b).Count();

您需要通配符作为附加的可能
true
条件进行计数。因此,您需要使用OR
|
而不是AND
&

不是:

int index=str1.Zip(str2,(c1,c2)=>c1==c2&&c2!='?').TakeWhile(b=>b.Count()

相反:

int index=str1.Zip(str2,(c1,c2)=>c1==c2 | | c2='?')).TakeWhile(b=>b.Count()

如果还希望忽略第一个输入中的通配符,则可以在表达式中添加额外的
|

使用linq


以下是经过全面测试的解决方案:

            string input1 = "1,1,0,0,0,0,0,0,0,0,0,0";
            string input2 = "\u003F,\u003F,1,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F";

            int results = input1.Select((x, i) => new { chr = x, index = i }).Where(x => (x.chr != input2[x.index]) && (x.chr != '\u003F') && (input2[x.index] != '\u003F')).Min(x => x.index);

c1==c2 | c2=='?'
            string input1 = "1,1,0,0,0,0,0,0,0,0,0,0";
            string input2 = "\u003F,\u003F,1,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F,\u003F";

            int results = input1.Select((x, i) => new { chr = x, index = i }).Where(x => (x.chr != input2[x.index]) && (x.chr != '\u003F') && (input2[x.index] != '\u003F')).Min(x => x.index);