从字符串列表中返回潜在字符串及其下一个字符性能

时间:2012-01-25 18:27:50

标签: c# .net string performance algorithm

这是一个关于从字符串数组中高效返回字符串和字符的问题,其中:

  1. 字符串数组中的字符串以提供的用户输入开头
  2. 这些字符串的下一个字母作为字符集合。
  3. 这个想法是当用户键入一个字母时,潜在的响应会与下一个字母一起显示。因此响应时间很重要,因此需要一个高性能的算法。

    E.g。如果字符串数组包含:

    string[] stringArray = new string[] { "Moose", "Mouse", "Moorhen", "Leopard", "Aardvark" };
    

    如果用户输入“Mo”,那么“Moose”,“Mouse”和“Moorhen”应该与字母“o”和“u”一起返回以查找潜在的下一个字母。

    这感觉就像LINQ的工作一样,所以我作为静态方法的当前实现是(我将输出存储到一个Suggestions对象,该对象只有2个返回列表的属性):

    public static Suggestions 
    GetSuggestions
        (String userInput, 
        String[] stringArray)
    {
        // Get all possible strings based on the user input. This will always contain
        // values which are the same length or longer than the user input.
        IEnumerable<string> possibleStrings = stringArray.Where(x => x.StartsWith(userInput));
        IEnumerable<char> nextLetterChars = null;
    
        // If we have possible strings and we have some input, get the next letter(s)
        if (possibleStrings.Any() &&
            !string.IsNullOrEmpty(userInput))
        {
            // the user input contains chars, so lets find the possible next letters.
            nextLetterChars =
                possibleStrings.Select<string, char>
                (x =>
                {
                    // The input is the same as the possible string so return an empty char.
                    if (x == userInput)
                    {
                        return '\0';
                    }
                    else
                    {
                        // Remove the user input from the start of the possible string, then get
                        // the next character.
                        return x.Substring(userInput.Length, x.Length - userInput.Length)[0];
                    }
                });
        } // End if
    

    我实现了第二个版本,它实际上将所有输入组合存储到字典列表中;每个单词一个,组合键和值作为所需的实际动物,例如:

    • 字典1:
    • 键值
    • “M”“驼鹿”
    • “MO”Moose“

    • 字典2:
    • 键值
    • “M”“Mouse”
    • “MO”“Mouse”

    由于字典访问有一个O(1)检索时间 - 我想也许这是一个更好的方法。

    所以在启动时加载词典:

        List<Dictionary<string, string>> animalCombinations = new List<Dictionary<string, string>>();
        foreach (string animal in stringArray)
        {
            Dictionary<string, string> animalCombination = new Dictionary<string, string>();
            string accumulatedAnimalString = string.Empty;
            foreach (char character in animal)
            {
                accumulatedAnimalString += character;
                animalCombination[accumulatedAnimalString] = animal;
            }
    
            animalCombinations.Add(animalCombination);
        }
    

    然后在运行时获取可能的字符串:

        // Select value entries from the list of dictionaries which contain
        // keys which match the user input and flatten into one list.
        IEnumerable<string> possibleStrings = 
            animalCombinations.SelectMany
                (animalCombination => 
                    {
                        return animalCombination.Values.Where(x =>
                            animalCombination.ContainsKey(userInput));
                    });
    

    所以问题是:

    1. 哪种方法更好?
    2. 有更好的方法可以提高性能吗?
    3. LINQ表达式处理起来是否昂贵?
    4. 由于

1 个答案:

答案 0 :(得分:9)

  

哪种方法更好?

可能是字典方法,但你必须要进行剖析以找出答案。

  

有更好的方法可以提高性能吗?

使用prefix tree

  

LINQ表达式处理起来是否昂贵?

写得正确,他们将非常的开销添加到相同代码的命令式版本中。由于它们更易于阅读,维护和编写,因此通常可以采用它们。