【问题标题】:C# check if a string contains all characters in a list accounting for duplicatesC# 检查字符串是否包含列表中的所有字符,以解决重复问题
【发布时间】:2016-05-21 12:49:49
【问题描述】:

如何检查一个字符串是否可以由字符列表(或数组)中的字符组成,同时考虑重复的字母。

所以,假设我有字符串(或字符数组/列表/任何东西)“abcc”和字符列表(或数组/字符串/任何东西,它都可以转换为任何东西)“['c'],[ 'b'],['a']"。如何将这两个值相互检查,但还要考虑到 'c' 在 char 数组中只存在一次,因此它应该会失败。

我知道我可以使用“.Contains”轻松地做到这一点,并遍历整个字符数组,从数组中删除某个字符,或者使用“IndexOf”并做同样的事情,但我会想知道是否有办法不从 char 数组中删除任何项目。

【问题讨论】:

  • 您的意思是c 在 char 数组中不止一次存在并且应该失败吗? vs 你在这里写的How would one go about checking those two values against each other but also account that 'c' exists only once in the char array and therefore it should fail.
  • @MethodMan 是的,我认为我的解释会有点令人困惑,因为我不擅长解释事情。基本上,您有一个字符池(在本例中是一个 char 数组)和一个字符串。我希望能够检查是否可以从池中存在的字符构建字符串,这通过检查 .IndexOf 和 .Contains 之类的内容很简单,但这些不考虑重复的字母。
  • 如果您知道 linq,您可以检查字符串中的重复项。如果您知道 linq,您还可以检查字符串是否包含重复项并返回计数或值以及字符串是否包含数组或字符..
  • @ChristianC 有很多优秀的在线教程,MSDN 提供了各种示例的免费下载,您可以逐步浏览并使用调试器MSDN 101 LINQ Samples in C#

标签: c# .net arrays char contains


【解决方案1】:
var input = "abbc";
var validChars = new List<char>() { 'c', 'b', 'a' };
var invalidChars = validChars.Where(validChar => input.Count(inputChar => inputChar == validChar) > 1);

然后你可以检查invalidChars是否有条目。

编辑:我将保留我原来的回复,但根据您的反馈,我认为这是正确的程序。

首先,我认为最好将您的字符数组转换为某种字典,以 char 作为键,以 int 作为值(告诉您该字母有多少可用)。

var charPool = new Dictionary<char, int>()
{
   { 'a', 2 },
   { 'b', 5 },
   { 'c', 5 },
   { 'd', 5 },
   { 'f', 0 },
   ...
   { 'z', 5 }
};

从那里,您可以获取输入字符串并应用一些 LINQ 来根据条件过滤值。我选择了!charPool.ContainsKey(inputChar)charPool[inputChar] &lt; inputWord.Count(c =&gt; c == inputChar) 作为我的匹配标准。这些基本上说明“对于应用此过滤器的每个字符,如果 1. 字典中不存在该键,或者 2. 字典中该字符的值或数量小于该字符在输入字符串,则该字符无效。

给定一个输入字符串

var inputWord = "bananafone";

以下代码应返回字母 afe 的 IEnumerable。 a,因为我们需要 3 而只有 2; f,因为我们的入口是0,我们需要1;和e,因为该字母不存在条目。此外,还使用了 .Distinct(),因为没有它,在本例中,a 将在遍历输入字符串并应用过滤器时被输入 3 次。

var charsNeeded = inputWord.Where(inputChar => !charPool.ContainsKey(inputChar) || charPool[inputChar] < inputWord.Count(c => c == inputChar)).Distinct();

请注意,这种方法的一个缺点是我们不计算我们拥有的字符数和需要的字符数之间的差异。但是我认为实施起来不会很困难;例如,您可以轻松地为输入字符串创建另一个字典,然后比较两者。

【讨论】:

  • 我想喜欢你的回答,但我不知道 Linq 有那么好。
  • 也许我可以带您了解一下。快速的问题——你的字符数组是独一无二的吗?如果数组有例如两个'b',字符串是否需要正好有两个b?
  • 所以想像拼字游戏这样的东西。如果你有字母“e,c,c,h,k,o,n”,那么你可以写成“cone”、“echo”或“check”。所以字符串不需要用完所有的字母,但它不能使用不存在的字母。
  • 这个答案是如此接近,所以我会给你接受的答案,即使它不完全存在,我可能可以用它来做我想做的事。
  • 稍后,我将更新我的帖子并进行一些更改。
【解决方案2】:

如果您要处理大量字符并且它们都是 ASCII 字符,那么为了保持高效,我会考虑遍历两个字符串并计算每个字符出现的频率。

【讨论】:

    【解决方案3】:

    使用您的拼字游戏评论,如何:获取输入中每个字符的总计数,并将其与允许的字符列表中相同字符的计数进行比较。如果输入字符串包含的字符多于允许的字符列表,则输入字符串无效。

    private static bool ValidateString(string input)
        {
            bool retValue = true;
            char[] validChars = { 'a', 'b', 'd' };
            foreach (var character in input)
            {
                //count the number of times the character occurs in the input string
                var characterCount = input.Count(c => c == character);
                //count the number of times the character occurs in the allowed char array
                var allowedCharacterCount = validChars.Count(c => c == character);
                //if the string contains more than the character array allows, immediately fail.
                if (characterCount > allowedCharacterCount)
                {
                    retValue = false;
                    break;
                }
    
            }
            return retValue;
    
        }
    

    这可能不是最有效的处理方式,尤其是在字符串有效的情况下,因为它逐个字符地遍历整个字符串。但我认为它很实用。

    【讨论】:

    • 这实际上非常好,但最后,我确实认为我会继续循环,并删除使用的字母。即:foreach( char c in candidate) { if (availableLetters.IndexOf(c) != -1) availableLetters.RemoveAt(availableLetters.IndexOf(c)); }
    【解决方案4】:

    我想您可以通过转换为 char 数组来创建字符串中每个字母的计数来解决此问题,如果您的情况是 3 个 int (a,b,c) 或带有 ( 0-25) 其中 a=1 b=1 和 c=2 然后通过对另一个数组做同样的事情进行比较,并说如果您检查字符串的数组的值 >= 到其中一个字符串的值然后你很好,你可以继续检查 b 直到你检查你的 c 值 2 是否 >= 到 c=1 的另一个值并且你得到 false 所以它停止。

    【讨论】:

      【解决方案5】:

      您可以将搜索列表(即您在目标字符串中搜索 FOR 的字符列表)设为数组或对象列表,而不仅仅是字符。然后你可以有一个与每个字符关联的布尔值来指示“IsFoundInTarget”——这样你就可以“标记”每个字符而不删除它。最后,执行.Find(x=&gt; x.Character == TheCharacterBeingSearchedFor &amp;&amp; x.IsFoundInTarget == False) 或类似的操作来处理一个字符的多次出现。

      【讨论】:

        【解决方案6】:

        我们可以使用默认方法包含 var str="拉梅什"; str.contains("s").Count();

        【讨论】:

          【解决方案7】:

          Linq 并不难理解,如果你愿意,可以将其分解为两个步骤

          第一个

          //Check to see if the input values exist in the collection
          var input = "abbc";
          var collection = new List<char>() { 'c', 'b', 'a' };
          bool doesContain = collection.Any(item => input.Contains((char)item));
          

          doesContain 将返回 true

          第二个

          //check for duplicates in the input variable
          var duplicatesList = input.GroupBy(s => s)
              .SelectMany(grp => grp.Skip(1)).ToList();
          

          使用调试器会返回b

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-21
            • 2020-02-26
            • 1970-01-01
            • 2019-06-07
            • 1970-01-01
            相关资源
            最近更新 更多