1

我有一个关于如何比较两个字符串的问题。

这是代码。

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

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

我想要的结果应该是 TRUE。

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

感谢大家。

更新

感谢大家的热心回复。

这是我的澄清

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

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

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

有什么建议吗?

另一个更新

再次感谢你的帮助。

我确实喜欢 Peter Ritchie、codesparkle、Dave 和 EdFred 的建议。

4

9 回答 9

6

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

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 中执行的东西,那么您可能需要其他东西。

于 2012-08-14T02:47:32.850 回答
4

试试这个方法:

  • 将每个字符串中的每个单词放入字符串数组中
  • 按字母顺序对每个单词数组进行排序
  • 比较数组是否相等
于 2012-08-14T02:45:55.720 回答
2

我会将字符串拆分为标记并测试 stringA 中的所有标记是否存在于 stringB 的标记列表中。就像是:

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

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

于 2012-08-14T02:54:08.960 回答
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;
    }
于 2012-08-14T02:55:18.597 回答
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

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

public static bool ContainsSameWordsAs(this string first, string second)
{
    var ignoreCase = StringComparer.OrdinalIgnoreCase;
    return first.Split().Any(word => second.Split().Contains(word, ignoreCase));
}

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

于 2012-08-14T03:57:48.143 回答
1
stringA.OrderBy(c => c).SequenceEqual(stringB.OrderBy(c => c));

编辑 哎呀。错误的做法。那会教我回答太快。

我相信这应该有效:

stringA.Split(' ').OrderBy(w => w).SequenceEqual(stringB.Split(' ').OrderBy(w => w));
于 2012-08-14T02:46:12.373 回答
1

我会做一个2阶段的比较:

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

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

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

迈克尔·G。

于 2012-08-14T02:46:36.443 回答
0

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

如果第一个字符串中的单词在集合 words1 中,而第二个字符串中的单词在 words2 中,则可以执行以下操作:

if(!words1.Intersect(words2).Except( words1).Any()) -> your sentences are 'equal'
于 2012-08-14T02:47:08.413 回答
0
        bool match = true;
        string[] stringBSplit = stringB.Split(' ');
        foreach (string aString in stringA.Split((' ')))
        {
            if (!stringBSplit.Contains(aString))
            {
                match = false;
                break;
            }
        }
于 2012-08-14T02:59:15.973 回答