0

我在 C# 中有一个很长的单词列表,我想在该列表中找到具有相同首尾字母且长度介于 5 到 7 个字符之间的所有单词。例如,列表可能有:

“浪费了被洗了洗了洗了看着手表枯萎了废物智慧洗涤物”

它会回来

长度:5-7,第一个字母:w,最后一个字母:d,“wasted,washed,looking” 长度:5-7,第一个字母:w,最后一个字母:s,“washes, watch, wilts, wastes”

然后我可能会将规范更改为 3-4 个字符的长度,这将返回

长度:3-4,第一个字母:w,最后一个字母:s,“was, wits”

我发现这种拆分方法非常快,使每个项目都独一无二,使用长度并给出了一个很好的开始: Spliting string into words length-based lists c#

有没有办法修改/使用它来考虑第一个和最后一个字母?

编辑

我最初询问“最快”的方式是因为我通常使用大量字符串数组(速度慢且涉及大量代码)来解决此类问题。LINQ 和查找对我来说是新的,但我可以看到我链接到的解决方案中使用的 ILookup 的简单性令人惊叹,而且速度非常快。我实际上并不需要最少的处理器时间。任何避免我为这些信息创建单独数组的方法都很棒。

4

5 回答 5

2

这一个班轮将为您提供在您的范围内具有相同第一个/最后一个字母的组

 int min = 5;
 int max = 7;
 var results = str.Split()
                     .Where(s => s.Length >= min && s.Length <= max)
                     .GroupBy(s => new { First = s.First(), Last = s.Last()});
于 2014-03-28T19:13:27.313 回答
0

正如一个快速的想法,我不知道这是否会比发布的 linq 解决方案更快或更有效,但这也可以使用正则表达式相当容易地完成。

例如,如果您想获得以“w”开头并以“s”结尾的 5-7 个字母长度的单词,您可以使用以下模式:

\bw[A-Za-z]{3,5}s\b

(这可以很容易地被更多变量驱动 - 例如,为第一个字母、最小长度、最大长度、最后一个字母设置一个变量并将它们插入到模式中以替换 w、3、5 和 s)

他们,使用 RegEx 库,然后您可以将捕获的组作为您的列表。

同样,我不知道这如何将效率与 linq 进行比较,但我认为它可能值得一提。

希望这可以帮助!!

于 2014-03-28T19:29:54.303 回答
0

这是一种完全符合您要求的方法。你只得到一个字符串列表和最小/最大长度,对吗?您没有获得过滤的第一个和最后一个字母。此方法处理字符串中的所有第一个/最后一个字母。

private static void ProcessInput(string[] words, int minLength, int maxLength)
{
    var groups = from word in words
                 where word.Length > 0 && word.Length >= minLength && word.Length <= maxLength
                 let key = new Tuple<char, char>(word.First(), word.Last())
                 group word by key into @group
                 orderby Char.ToLowerInvariant(@group.Key.Item1), @group.Key.Item1, Char.ToLowerInvariant(@group.Key.Item2), @group.Key.Item2
                 select @group;
    Console.WriteLine("Length: {0}-{1}", minLength, maxLength);
    foreach (var group in groups)
    {
        Console.WriteLine("First letter: {0}, Last letter: {1}", group.Key.Item1, group.Key.Item2);
        foreach (var word in group)
            Console.WriteLine("\t{0}", word);
    }
}
于 2014-03-28T19:19:37.807 回答
0

就在 LINQPad 中,我创建了这个:

void Main()
{
var words = new []{"wasted", "was", "washed", "washing", "was", "washes", "watched", "watches", "wilts", "with", "wastes", "wits", "washings"};

var firstLetter = "w";
var lastLetter = "d";
var minimumLength = 5;
var maximumLength = 7;

var sortedWords = words.Where(w => w.StartsWith(firstLetter) && w.EndsWith(lastLetter) && w.Length >= minimumLength && w.Length <= maximumLength);
sortedWords.Dump();
}

如果这还不够快,我会创建一个查找表:

Dictionary<char, Dictionary<char, List<string>> lookupTable;

并做:

lookupTable[firstLetter][lastLetter].Where(<check length>)
于 2014-03-28T19:12:29.140 回答
0
var minLength = 5;
var maxLength = 7;
var firstPart = "w";
var lastPart = "d";

var words = new List<string> { "washed", "wash" }; // so on

var matches = words.Where(w => w.Length >= minLength && w.Length <= maxLength && 
                               w.StartsWith(firstPart) && w.EndsWith(lastPart))
                   .ToList();

在大多数情况下,这应该足够快,除非您正在处理数万个单词并担心 ms。然后我们可以看得更远。

于 2014-03-28T19:11:31.567 回答