排除字符串列表中的相似性以提取差异

除了书的标题之外,我有一个相同的句子列表。

如何循环列表并排除相似性以找到书的标题?

(这是一个例子,它可以是任何具有相似性的短句。)

这本名为蝇王的书是经典之作。
名为To Kill a Mockingbird的书是经典之作。
这本名为The Catcher in the Rye的书是经典之作。


我遇到的问题是我不能简单地使用regexContains()来查找句子中的标题,因为我不知道下一个句子或书名是什么。 我正在从外部来源搜索很多,所以我想我可以提取相似词之间的内容。

The book named The Catcher in the Rye The book named is a classic


 List sentences = new List() { }; List titles = new List() { }; sentences.Add("The book named Lord of the Flies is a classic."); sentences.Add("The book named To Kill a Mockingbird is a classic."); sentences.Add("The book named The Catcher in the Rye is a classic."); foreach (String title in sentences) { // what to do here? // add title to titles list } 

我的想法是将列表中的所有字符串相互比较,排除字符串的相似部分,然后保留标题。 但我不知道如何去做。

这是一个有趣的问题,所以我已经玩了一点,并提出了以下(繁琐)解决方案:

找到任何句子具有不同字符的第一个索引,然后在反向句子中执行相同操作,然后使用Substring仅提取句子的不同部分:

 List ExtractDifferences(List sentences) { var firstDiffIndex = GetFirstDifferenceIndex(sentences); var lastDiffIndex = GetFirstDifferenceIndex(sentences.Select(s => new string(s.Reverse().ToArray())).ToList()); return sentences.Select(s => s.Substring(firstDiffIndex, s.Length - lastDiffIndex - firstDiffIndex)).ToList(); } int GetFirstDifferenceIndex(IList strings) { int firstDifferenceIndex = int.MaxValue; for (int i = 0; i < strings.Count; i++) { var current = strings[i]; var prev = strings[i == 0 ? strings.Count - 1 : i - 1]; var firstDiffIndex = current .Select((c, j) => new { CurrentChar = c, Index = j }) .FirstOrDefault(ci => ci.CurrentChar != prev[ci.Index]) .Index; if (firstDiffIndex < firstDifferenceIndex) { firstDifferenceIndex = firstDiffIndex; } } return firstDifferenceIndex; } 

我猜GetFirstDifferenceIndex方法可以用不同的方式编写,也许使用linq更好,但我没有足够的时间来使用它。

您可以在rextester上看到现场演示。

使用LINQ的工作解决方案:

 List sentences = new List() { }; List titles = new List() { }; sentences.Add("The book named Lord of the Flies is a classic."); sentences.Add("The book named To Kill a Mockingbird is a classic."); sentences.Add("The book named The Catcher in the Rye is a classic."); sentences.Add("Hello"); sentences.Add("The book named "); titles = sentences.Where(sentence => sentence.Length > "The book named ".Length + " is a classic".Length) .GroupBy(sentence => sentence.Substring(0, 15), sentence => sentence.Remove(sentence.Length - " is a classic".Length).Substring("The book named ".Length)) .Where(g => g.Key == "The book named ") .SelectMany(g => g) .ToList(); foreach (var title in titles) WriteLine(title); 

首先,它过滤掉句子太短而不符合标准,然后将结果按前15个字母分组,并用String.Remove提取标题。