我非常接近这一点。如果我能看一下这个问题,我昨天就向我提出了一个问题。
我感觉很亲密,但我认为这里的一些人也会很欣赏这个挑战而且我迷失了。
如果我的List<string>
有以下成员:
今天
周一 周二星期三
我想获得一个返回字符串day
,因为这是List<string>
中的最大公共字符串。无论位置和字符串长度如何,都应该这样做,只想在一大串字符串中找到最大长度的公共字符串。
我的尝试失败了一点,我选择了:
周一至周二
周一至周三
然后在每个之间做了Intersect
。显然这会返回多个字符串,但是对于Monday - Wednesday
,您会得到nday
,因为这就是它常见的字母。
这是我的代码:
List<string> strs = new List<string>();
strs.Add("Monday");
strs.Add("Tuesday");
strs.Add("Wednesday");
var v = strs.SelectMany((day, i) => strs.Select((day2, j) => new
{
iDay = i,
Day = day,
iDay2 = j,
Day2 = day2
})).Where(x => x.iDay != x.iDay2).Select(x => new string(x.Day.Intersect(x.Day2).ToArray()));
任何人都有一个很好的解决方案吗?
注意
它不一定是LINQ
如果没有常用字符串,请返回null
或空字符串。
答案 0 :(得分:7)
这比我的第一种方法(罢工)更好。
您可以使用以下扩展名来获取列表中最短字符串的所有子字符串(以提高效率):
public static IEnumerable<string> getAllSubstrings(this string word)
{
return from charIndex1 in Enumerable.Range(0, word.Length)
from charIndex2 in Enumerable.Range(0, word.Length - charIndex1 + 1)
where charIndex2 > 0
select word.Substring(charIndex1, charIndex2);
}
Length
(最长的第一个)Enumerable.All
如果一个字符串不包含给定的子字符串则立即返回)string shortest = list.OrderBy(s => s.Length).First();
IEnumerable<string> shortestSubstrings = shortest
.getAllSubstrings()
.OrderByDescending(s => s.Length);
var other = list.Where(s => s != shortest).ToArray();
string longestCommonIntersection = string.Empty;
foreach (string subStr in shortestSubstrings)
{
bool allContains = other.All(s => s.Contains(subStr));
if (allContains)
{
longestCommonIntersection = subStr;
break;
}
}
答案 1 :(得分:3)
找到列表中最短的条目。
所以我们使用“今天”。
以“最长的第一个”顺序在每个字符的字符串长度的“今天”中构建一个连续字符串的列表。
“今天”,
“Tod”,“oda”,“day”,
“To”,“od”,“da”,“ay”,
“t”,“o”,“d”,“a”,“y”
枚举此列表,找到所有其他字符串包含该条目的第一个条目。
List<string> words = new List<string> { "Today", "Monday", "Tuesday", "Wednesday" };
// Select shortest word in the list
string shortestWord = (from word in words
orderby word.Length
select word).First();
int shortWordLength = shortestWord.Length;
// Build up the list of consecutive character strings, in length order.
List<string> parts = new List<string>();
for (int partLength = shortWordLength; partLength > 0; partLength--)
{
for (int partStartIndex = 0; partStartIndex <= shortWordLength - partLength; partStartIndex++)
{
parts.Add(shortestWord.Substring(partStartIndex, partLength));
}
}
// Find the first part which is in all the words.
string longestSubString = (from part in parts where words.All(s => s.Contains(part)) select part).FirstOrDefault();
// longestSubString is the longest part of all the words, or null if no matches are found.
修改强>
稍微考虑一下,你可以稍微优化一下。
您无需建立零件清单 - 只需在生成零件时对其进行测试即可。此外,通过按长度顺序对单词列表进行排序,您总是先测试最短的字符串,以便更快地拒绝候选部分。
string longestSubString = null;
List<string> words = new List<string> { "Todays", "Monday", "Tuesday" };
// Sort word list by length
List<string> wordsInLengthOrder = (from word in words
orderby word.Length
select word).ToList();
string shortestWord = wordsInLengthOrder[0];
int shortWordLength = shortestWord.Length;
// Work through the consecutive character strings, in length order.
for (int partLength = shortWordLength; (partLength > 0) && (longestSubString == null); partLength--)
{
for (int partStartIndex = 0; partStartIndex <= shortWordLength - partLength; partStartIndex++)
{
string part = shortestWord.Substring(partStartIndex, partLength);
// Test if all the words in the sorted list contain the part.
if (wordsInLengthOrder.All(s => s.Contains(part)))
{
longestSubString = part;
break;
}
}
}
Console.WriteLine(longestSubString);