分割字符串列表以匹配第一个和最后一个字母的最佳方法是什么?

时间:2014-03-28 18:59:36

标签: c# string list lookup ilookup

我在C#中有很长的单词列表,我希望找到该列表中所有具有相同的第一个和最后一个字母并且长度介于5到7个字符之间的单词。例如,列表可能包含:

  

"浪费了洗涤洗涤洗涤看着手表枯萎与废物洗涤"

它将返回

  

长度:5-7,第一个字母:w,最后一个字母:d,"浪费,洗涤,观看"   长度:5-7,第一个字母:w,最后一个字母:s,"洗涤,手表,枯萎,废物"

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

  

长度:3-4,第一个字母:w,最后一个字母:s,"是,智慧"

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

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

修改

我最初问过最快的'因为我通常用很多字符串数组解决这样的问题(这很慢并涉及很多代码)。 LINQ和查找对我来说是新的,但我可以看到我链接到的解决方案中使用的ILookup简单而且非常快。我实际上并不需要最短的处理器时间。任何避免为这些信息创建单独数组的方法都会很棒。

5 个答案:

答案 0 :(得分: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()});

答案 1 :(得分: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。然后我们可以进一步了解。

答案 2 :(得分: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>)

答案 3 :(得分: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);
    }
}

答案 4 :(得分:0)

正如一个快速思考,如果这比发布的linq解决方案更快或更有效,我有无线索,但这也可以通过正则表达式相当容易地完成。

例如,如果你想得到5-7个以&#34; w&#34;开头的字母长度的单词。并以&#34; s&#34;结束,您可以使用以下行的模式:

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

(这可以很容易地变得更加变量驱动 - 例如,有一个变量用于第一个字母,最小长度,最大长度,最后一个字母并将它们插入到模式中以替换w,3,5和amp ; s)

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

同样,我不知道这与linq的效率比较,但我认为值得一提。

希望这会有所帮助!!