C# 检查一个字符串是否包含列表中的所有字符以计算重复项

C# check if a string contains all characters in a list accounting for duplicates

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

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

我知道我可以使用“.Contains”和 运行 通过整个字符数组轻松地从数组中删除该特定字符,或者使用 "IndexOf" 并执行此操作同样的事情,但我想知道是否有任何方法可以不从 char 数组中删除任何项目。

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

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

您可以将搜索列表(即您在目标字符串中搜索的字符列表)设为数组或对象列表,而不仅仅是字符。然后你可以有一个与每个字符相关联的布尔值来指示 "IsFoundInTarget" - 这样你就可以 "mark" 每个字符而不删除它。最后,做一个 .Find(x=> x.Character == TheCharacterBeingSearchedFor && x.IsFoundInTarget == False) 或类似的事情来处理一个字符的多次出现。

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] < inputWord.Count(c => c == inputChar) 作为我的匹配条件。这些基本上声明“对于应用此过滤器的每个字符,如果 1. 字典中不存在该键,或者 2. 字典中该字符的值或数量小于该字符在输入字符串,则该字符无效。

给定输入字符串

var inputWord = "bananafone";

下面的代码应该 return 一个由字母 afe 组成的 IEnumerable。 a,因为我们需要3个而只有2个; f,因为我们的entry是0,需要1;和 e,因为不存在该字母的条目。此外,使用 .Distinct() 是因为如果没有它,对于此示例,a 将在遍历输入字符串并应用过滤器时输入 3 次。

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

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

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 将 return true

第 2

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

使用调试器它将 return b

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

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;

    }

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

我们可以使用默认方法包含 变量 str="Ramesh"; str.contains("s").Count();