【问题标题】:Comparing Strings using LINQ in C#在 C# 中使用 LINQ 比较字符串
【发布时间】:2010-07-21 12:18:53
【问题描述】:

我有两个字符串

喜欢

  "0101000000110110000010010011" and
  "0101XXXXXXX101100000100100XX"

它应该比较每个字符,它不应该考虑字符是否是X

以上两个字符串结果为真。

现在我正在使用喜欢

遍历字符串的长度并将第一个字符串中的对应字符替换为X

有没有办法使用 LINQ 来做到这一点

【问题讨论】:

  • 谁说过SQL?这是可能的..当你说忽略..你的意思是跳到下一个字符吗?或者如果两者都是 X 跳过?
  • 您知道,如果您将二进制字符串作为解析网络或电信协议的一部分,那么您完全走错了路。在这种情况下,您应该真正解析包含为一系列对象的数据并比较结果对象...

标签: c# linq


【解决方案1】:

这在 .NET 4 中相当容易,使用 Zip 方法:

using System;
using System.Linq;

class Test
{
    static void Main()
    {
        string a = "0101000000110110000010010011";
        string b = "0101XXXXXXX101100000100100XX";

        var equal = !(a.Zip(b, (x, y) => new { x, y })
                       .Where(z => z.x != z.y && z.x != 'X' && z.y != 'X')
                       .Any());

        Console.WriteLine(equal);
    }
}

这基本上将两个字符串压缩在一起(将它们视为字符序列),因此我们最终得到成对序列。然后,我们尝试找到值不同且两个值都不是“X”的任何对。如果存在任何这样的对,则字符串不相等;否则他们是平等的。

编辑:进一步考虑,我们可以反转谓词并改用All

var equal = a.Zip(b, (x, y) => new { x, y })
             .All(z => z.x == z.y || z.x == 'X' || z.y == 'X');

如果您不使用 .NET 4,则可以使用 Zip 的 MoreLINQ 实现,它基本上可以让您做同样的事情。

或者,您可以像这样使用索引器压缩字符串:

var equal = Enumerable.Range(0, a.Length)
                      .Select(i => new { x = a[i], y = b[i] })
                      .All(z => z.x == z.y || z.x == 'X' || z.y == 'X');

感觉有点作弊,但确实有效。请注意,在所有这些示例中,我假设您已经检查了输入字符串的长度是否相同。

【讨论】:

  • @Jon Skeet:请给我一个在 .NET 3.5 中执行此操作的方法
  • @jon,我已经添加了我的答案.. 我的方法推荐性能是否明智...??
  • @Ramesh:这取决于你的性能要求是什么。与最快的解决方案相比,您的解决方案不是很快。 但如果它不需要非常快,那么谁在乎呢? 说明你的性能要求,然后测量你的代码,看看你是否满足它。
  • @Eric,我目前没有选择在 .net 4.0 中试用 zip 方法... :( 我的意思是在这种情况下它可以与 zip 方法相媲美吗??
  • @Ramesh:试试看!那你就知道了。我已将 Zip 的源代码放在我的博客上。 blogs.msdn.com/b/ericlippert/archive/2009/05/07/zip-me-up.aspx 只有几行代码。您可以比较一下,看看哪个表现更好。
【解决方案2】:

您可以创建一个custom comparer,然后使用SequenceEqual 方法:

string s1 = "0101000000110110000010010011";
string s2 = "0101XXXXXXX101100000100100XX";

bool areEqual = s1.SequenceEqual(s2, new IgnoreXEqualityComparer());    // True

// ...

public class IgnoreXEqualityComparer : EqualityComparer<char>
{
    public override bool Equals(char x, char y)
    {
        return (x == 'X') || (y == 'X') || (x == y);
    }

    public override int GetHashCode(char obj)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 我认为...我只是不喜欢不实现散列部分的想法。
  • @Jon:是的,它确实感觉有点不对劲,即使是一次性使用。如果我在自己的代码中执行此操作,那么我可能会完全避免使用 LINQ 并使用普通的 for 循环,直接索引到字符串。
【解决方案3】:

这应该可以。

        var a1 = "0101000000110110000010010011";
        var a2 = "0101XXXXXXX101100000100100XX";
        var notmatched = a2.Select((cha, idx) =>
        {
            if (cha != 'X')
               return (cha == a1[idx]) ? true : false;
            else
                return true;
         }).Any(x => x == false);

        if (notmatched)
            //strings are not match
        else
            //strings are match

【讨论】:

  • 对每个字符串调用 ToCharArray() 的任何理由?您可以对字符串进行索引,而无需将其转换为数组。
  • @jon,我打电话给 ToCharArray() 因为 VS 2008 不显示字符串扩展方法....后来我发现这是原因stackoverflow.com/questions/345883/….. 血腥混乱..
【解决方案4】:

如果你没有 X,我会知道路的。但是,使用 X 时,您无法像我所知的那样使用 Linq 做到这一点。

不管怎样,把它们做成 char 数组然后做:

arrayOne.Distinct(arrayTwo).ToArray().Length == 0

编辑: 我刚想到,您可以检查该结果是否仅包含X。如果是,则返回 true。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多