【问题标题】:filter a list of strings in C#在 C# 中过滤字符串列表
【发布时间】:2011-12-01 12:46:52
【问题描述】:

我正在通过阅读书籍和其他在线教程 (homeandlearn.co.uk) 来学习 C#

我已经成功完成了 FizzBu​​zz 练习,但在以下练习中遇到了困难。任何帮助将不胜感激。

请详细解释,以便我也可以学习。

练习

过滤一个字符串列表,该列表应该只传递六个字母字符串,这些字符串由两个串联的较小字符串组成,这些字符串也在列表中。

例如,给定列表

acks、top、cat、gr、by、bar、lap、st、ely、ades

列表应该返回

堆栈,笔记本电脑,成绩,勉强

因为这些是其他两个字符串的串联:

st + acks = 堆栈

膝上 + 顶部 = 笔记本电脑

gr + ades = 成绩

bar + ely = 勉强

【问题讨论】:

  • 过滤器是一个糟糕的词选择,构造会更好。
  • 除非示例错误并且堆栈也应该在列表中
  • cat+top = catop、gracks、byacks 等呢?练习写得不好。
  • 您缺少另一个列表:一组限制潜在结果的字典单词
  • 我希望年轻的英国男孩(和女孩)不会被教给 Excercise :-)

标签: c# string filter


【解决方案1】:

在 LINQ 中:

// The strings (it's equivalent to new string[])
var strs = new[] { "acks", "top", "cat", "gr", "by", "bar", "lap", "st", "ely", "ades" };

// We group the strings by length.
var strsByLength = strs.ToLookup(p => p.Length);

// For each string we match the string with all the strings with the "right" length (6 - current string length) and we sum them (p, q) => p + q.
var result = strs.SelectMany(p => strsByLength[6 - p.Length], (p, q) => p + q);

我使用ToLookup 使这个问题“中等”复杂度略低于 O(n^2)。显然如果所有字符串都是长3,问题仍然是O(n^2)。

我正在使用SelectMany,它本身就是一个有点高级的 LINQ。

我会补充一点,如果你有一本“好”字的字典,一个解决方案可能是这个。它将字典用作黑匣子:您可以检查一个单词是否在字典中(技术上是 HashSet),但您不能直接使用字典来帮助您查找单词。

// The list of good words
var words = new[] { "stacks", "laptop", "grades", "barely" };

// Made in an `HashSet` to make it O(1) to check for them.
var wordsSet = new HashSet<string>(words);

// Here we create a temporary object (p, q) => new { p, q, sum = p + q } containing the two "parts" of the word and the complete word and then we filter the result for only the words contained in the wordsSet.
var result2 = strs.SelectMany(p => strsByLength[6 - p.Length], (p, q) => new { p, q, sum = p + q }).Where(p => wordsSet.Contains(p.sum));

【讨论】:

    【解决方案2】:

    确实有很多方法可以做到这一点。这是使用配对的一个:

            //grab all possible pairings in one data structure
            List<KeyValuePair<string, string>> pairs = new List<KeyValuePair<string, string>>();
            string[] list = { "acks", "top", "cat", "gr", "by", "bar", "lap", "st", "ely", "ades" };
            foreach (string first in list)
            {
                foreach (string second in list)
                {
                    pairs.Add(new KeyValuePair<string, string>(first, second));
                }
            }
    
            //test each pairing for length and whatever else you want really
            List<string> sixLetterWords = new List<string>();
            foreach (KeyValuePair<string, string> pair in pairs)
            {
                string testWord = pair.Key + pair.Value;
                if (testWord.Length == 6)
                {
                    sixLetterWords.Add(testWord);
                }
            }
    

    【讨论】:

      【解决方案3】:

      分而治之。首先,您需要找到一种方法来获取所有可能的字符串对(如第一和第二、第一和第三、...、第二和第三等)。接下来,对于每一对,您检查相关列表是否包含s1 + s2s2 + s1

      【讨论】:

      • 感谢您的帮助,因为您知道我正在学习并且在 C# 方面非常基础,请您稍微详细说明一下,或者即使您可以编写快速代码,以便我可以学习和遵循。谢谢
      • 只值得创建关节长度为 6 的对。
      • @Mo. - 我们给你举个例子是没有用的。 Anton 建议的编程技能是微不足道的,你需要自己做,否则你什么也学不到。
      【解决方案4】:

      最简单的方法是做一个嵌套的 for 循环,并尝试每个组合并测试它的长度是否为 6。比如:

      For <each string> AS a
          For <every string> AS b
              If (a+b).length = 6 then
                  // we have a match!
      

      我会让你把它翻译成实际的代码

      【讨论】:

        【解决方案5】:

        您已经知道如何连接两个字符串。你也知道如何检查字符串的长度。

        因此,从第一个列表中的项目创建一个新列表,并排除长度为 != 6 的项目。

        【讨论】:

          猜你喜欢
          • 2020-11-13
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-10
          • 1970-01-01
          相关资源
          最近更新 更多