如何比较这两个字符串

时间:2012-08-14 02:41:19

标签: c# sql

我对如何比较两个字符串有疑问。

这是代码。

        string stringA = "This is a test item";
        string stringB = "item test a is This";

显然,stringB包含来自stringA的每个单词,但顺序不同。

我想要的结果应该是正确的。

我的问题是,我该怎么办?我曾尝试使用.Contains()方法,但结果为FALSE。

谢谢大家。

更新

感谢大家的亲切回复。

以下是我的澄清

我实际上是使用LINQ和EF构建数据库搜索功能。

假设一个项目的名称为“这是一个测试项目”。

如果用户输入“test a is this”,我希望该功能足够智能以捕捉上述项目。

有什么建议吗?

另一个更新

再次感谢您的帮助。

我确实喜欢Peter Ritchie,代码密码,Dave和EdFred的建议。

9 个答案:

答案 0 :(得分:6)

'String.Split'带有空格分隔符的单词,将结果数组排序到List中,然后比较列表。例如:

var x = new List<string>(stringA.Split(' '));
x.Sort();
var y = new List<string>(stringB.Split(' '));
y.Sort();
bool areEqual = x.SequenceEqual(y);

更新如果您想要不区分大小写:

var x = new List<string>(stringA.Split(' '));
x.Sort();
var y = new List<string>(stringB.Split(' '));
y.Sort();
bool areEqual = x.SequenceEqual(y, StringComparer.OrdinalIgnoreCase);

但是,如果您正在寻找将在SQL Server中执行的内容,那么您可能还需要其他内容。

答案 1 :(得分:4)

尝试这种方法:

  • 将每个字符串中的每个单词变为字符串数组
  • 按字母顺序对每个单词数组进行排序
  • 比较数组是否相等

答案 2 :(得分:2)

我会将字符串拆分为tokens并测试stringA中令牌列表中是否存在stringA中的所有标记。类似的东西:

var stringBTokens = stringB.Split(" ");
foreach(string token in stringA.Split(" "))
{
    if(stringBTokens.Contains(token) == false) return false;
}
return true;

可能有一些奇怪的正则表达式可以做到这一点,但这是一个相当直接的测试。如果你想获得幻想,你可以使用Linq Any方法,如下所示:

var stringBTokens = stringB.Split(" ");
return !stringBTokens.Any(token => stringA.Contains(token));

这基本上是做同样的事情,只是后者我发现更优雅。我希望没有错误,我在我的macbook pro上,并且没有安装.net相关(或单声道等等)以验证这是否有效。

<强>更新

根据您的澄清,我会看一下http://en.wikipedia.org/wiki/Inverted_index

这听起来像你想要实现的。我之前创建了这些,在数据库中进行快速文本搜索,并且它非常有效。

答案 3 :(得分:2)

模仿伯纳德的解释。

许多人遗漏了关键部分。在进行比较之前,需要转换字符串.ToLower()。

编辑:这就是你需要的。使Linq更具可读性。

 public static bool Compare (string wordOne, string wordTwo)
    {
        //split into words
        var wordsOne = wordOne.ToLower().Split(' ').ToList();
        var wordsTwo = wordTwo.ToLower().Split(' ').ToList();

        if (wordsOne.Count() != wordsTwo.Count()) {
            return false;
        }

        //sort alphabetically
        wordsOne.Sort((x,y) => string.Compare(x, y));
        wordsTwo.Sort((x,y) => string.Compare(x, y));

        //compare
        for (int i = 0; i < wordsOne.Count(); i++) {
            if(wordsOne[i] != wordsTwo[i])
                return false;
        }

        return true;
    }

答案 4 :(得分:1)

stringA.OrderBy(c => c).SequenceEqual(stringB.OrderBy(c => c));

修改 哎呀。错误的做法。这会教我回答得太快。

我相信这应该有效:

stringA.Split(' ').OrderBy(w => w).SequenceEqual(stringB.Split(' ').OrderBy(w => w));

答案 5 :(得分:1)

我会进行两阶段比较:

  1. 使用.Split('')方法拆分字符串并确保它们具有相同数量的元素(.Count属性)。

  2. 将新创建的数组(拆分字符串)转换为集合并执行A设置差异B联盟B设置差异A.

  3. 然后如果测试1通过并且设置差异的联合所创建的集合中没有元素(在测试2中),则您已成功比较了字符串中的单词,如上所述。

    Michael G。

答案 6 :(得分:1)

在Peter Richie提出的出色建议的基础上,使用Array.Sort()代替List<T>.Sort(),没有重复但是打包成一个简洁的扩展方法:

public static bool ContainsSameWordsAs(this string first, string second)
{
    return first.GetSortedWords().SequenceEqual(second.GetSortedWords());
    // if upper and lower case words should be seen as identical, use:
    // StringComparer.OrdinalIgnoreCase as a second argument to SequenceEqual
}

private static IEnumerable<string> GetSortedWords(this string source)
{
    var result = source.Split().ToArray();
    Array.Sort(result);
    return result;
}

<强>用法

string stringA = "This is a test item";
string stringB = "item test a is This";
string stringC = "Not the Same is This";
bool result = stringA.ContainsSameWordsAs(stringB);    // true
bool different = stringA.ContainsSameWordsAs(stringC); // false

编辑: 很难理解为什么您接受了不符合您问题中所述要求的答案。如果您真的想要字符串{{1}和"This is a test item"匹配,你需要使用更多涉及的东西,例如:

"test a is this"

你可能想要提出一个更好的算法,因为这个算法非常宽松 - 两个相同的词足以算作匹配。但是这个符合您在问题中所述的要求。

答案 7 :(得分:0)

您可以在空白处拆分字符串,并比较两个结果集合。您可以使用linq中的set operations

如果第一个字符串中的单词位于集合单词1中,而第二个字符串中的单词位于单词2中,则可以执行以下操作:

if(!words1.Intersect(words2).Except( words1).Any()) -> your sentences are 'equal'

答案 8 :(得分:0)

        bool match = true;
        string[] stringBSplit = stringB.Split(' ');
        foreach (string aString in stringA.Split((' ')))
        {
            if (!stringBSplit.Contains(aString))
            {
                match = false;
                break;
            }
        }