【问题标题】:How to get index of all matching chars in char array?如何获取char数组中所有匹配字符的索引?
【发布时间】:2014-12-07 07:33:00
【问题描述】:

我正在开发一个简单的刽子手程序。我的大部分代码都在工作,但我无法弄清楚如何获取 char 数组中多个匹配字符的索引。例如,我将单词“sushi”转换为 char 数组。如果用户猜到一个“s”,那么应该显示 char 数组中的所有“s”。我的代码的方式是,我实际上有两个长度相同的 char 数组。第一个数组保存要猜测的单词的字符,而第二个数组保存问号。我的代码应该遍历第一个数组并返回数组中与用户猜测匹配的 each 元素的索引。然后,代码在每个指定索引处插入用户猜测,并为用户显示第二个数组。不幸的是,只有第一个出现在第二个数组中发生了变化,所以只有第一个索引从匹配查询中返回。有问题的代码如下:

            //check if char array contains the user input
            if (guessThis.Contains(Convert.ToChar(textBox1.Text)))
            {
                //save user input as char
                char userGuess = Convert.ToChar(textBox1.Text);
                //iterate through first char array
                for (int i = 0; i < guessThis.Length - 1; i++ )
                {
                    //check each element in the array
                    //probably don't need both for and foreach loops
                    foreach (char c in guessThis)
                    {
                        //get index of any element that contains the userinput
                        var getIndex = Array.IndexOf(guessThis, c);
                        //check if the element matches the user guess
                        if (c == userGuess)
                        {
                            //insert the userguess into the index
                            displayAnswer[getIndex] = userGuess;

                        }
                    }

                }
                //update the display label
                answerLabel.Text = new string(displayAnswer);

已解决: 根据所选答案中的示例,我将代码更新为:

                //check if char array contains the user input
            if (guessThis.Contains(Convert.ToChar(textBox1.Text)))
            {
                //save user input as char
                char userGuess = Convert.ToChar(textBox1.Text);
                string maybeThis = textBox1.Text;
                string tryThis = new string(guessThis);
                foreach (Match m in Regex.Matches(tryThis, maybeThis))
                {
                    displayAnswer[m.Index] = userGuess;
                }
                answerLabel.Text = new string(displayAnswer);
            }

【问题讨论】:

    标签: c# arrays visual-studio-2010 foreach indexing


    【解决方案1】:

    尝试Regex.Matches 构建正则表达式并查找所有匹配项及其位置。

    using System;
    using System.Text.RegularExpressions;
    
    public class Example
    {
       public static void Main()
       {
          string pattern = "a*";
          string input = "abaabb";
    
          foreach (Match m in Regex.Matches(input, pattern)) 
             Console.WriteLine("'{0}' found at index {1}.", 
                               m.Value, m.Index);
       }
    }
    // The example displays the following output:
    //       'a' found at index 0.
    //       '' found at index 1.
    //       'aa' found at index 2.
    //       '' found at index 4.
    //       '' found at index 5.
    //       '' found at index 6.`
    

    http://msdn.microsoft.com/en-gb/library/system.text.regularexpressions.regex.matches(v=vs.110).aspx

    【讨论】:

    • @melnikovl 感谢您的示例!不幸的是,链接以不同的语言显示,但我能够弄清楚表达式的含义以及如何正确实现它。
    • 可能只是我,但我避免像瘟疫一样使用正则表达式。好慢!
    【解决方案2】:

    因为你的:

    var getIndex = Array.IndexOf(guessThis, c);
    

    总是返回第一次出现的字符。

    你的第二个 for 循环和 getIndex 没用,更清晰的代码可能是:

            for (int i = 0; i < guessThis.Length - 1; i++ )
            {
                //check if the element matches the user guess
                if (c == userGuess[i])
                {
                    //insert the userguess into the index
                    displayAnswer[i] = userGuess;
                }
            }
    

    此外,您的代码允许用户在 textBox1 中输入多个字符。我认为在这种游戏中,每次只能猜一个角色。所以我建议你限制你的输入。

    【讨论】:

    • 此代码实际上不起作用。有几个问题。首先,您不能在 userGuess[i] 上使用 [i],因为 userGuess 是一个字符,而不是一个数组。第二个问题是,如果你删除了 foreach 循环,那么“c”就变成了一个无效变量,因为它没有被声明,因此你不能将 userGuess 与“c”进行比较。如果您保留 foreach 循环并删除 [i],则代码将编译,但它只是将 displayAnswer 数组中的所有字符替换为用户猜测。此外,我已经实现了将用户限制为一个字符且仅限字母的代码。
    【解决方案3】:

    我认为问题出在方法上: var getIndex = Array.IndexOf(guessThis, c); 因为它返回第一个位置。 您可以只使用 for 循环中的索引

    【讨论】:

    • 是的,这就是问题的一部分。我猜这就是正在发生的事情。感谢您的验证。
    【解决方案4】:

    试试这样的:

            char userGuess = Convert.ToChar(textBox1.Text);
            char[] displayAnswer = answerLabel.Text.ToCharArray();
    
            for (int n = 0; n < displayAnswer.Length; n++)
            {
                if (guessThis[n] == userGuess)
                {
                    displayAnswer[n] = userGuess;
                    }
            }
            answerLabel.Text = new string(displayAnswer);
    

    一个简单的方法

    【讨论】:

    • answerlabel 默认显示的文本是 displayAnswer 数组中包含的问号。因此,用户输入的内容实际上不会匹配。我知道这在我发布的有限代码中并不清楚。否则,这可能会起作用。
    • displayAnswer的相关代码为: //循环遍历数组中的每个元素 for (int i = 0; i
    【解决方案5】:

    你可以做这样的事情(为了清楚起见,通用):

        public static IEnumerable<int> AllIndexesOfAny<T>(this IList<T> list, IEnumerable<T> ofAny)
        {
            return Enumerable.Range(0, list.Count).Where(i => ofAny.Contains(list[i]));
        }
    

    如果性能成为问题,您可以将IEnumerable&lt;T&gt; ofAny 替换为HashSet。

    更新

    仔细阅读您的代码,发现您正在通过guessThis 进行索引,并且对于guessThis 中的每个字符,在guessThis 中找到它的索引并检查它是否与thisGuess 匹配。这是不必要的。在guessThis 中查找与userGuess 匹配的所有字符索引的最简单的非通用方法可能是:

    var matches = Enumerable.Range(0, guessThis.Length).Where(i => guessThis[i] == userGuess);
    

    补充说明

    顺便说一句,这对您的应用程序可能无关紧要,但 .Net 中的一些非 ASCII Unicode 字符实际上由 surrogate pairs of chars 表示。 (还有 diacritical combining characters 修改了前面的字符。)在“国际化”刽子手游戏中,您可能希望通过将代理对转换为 UTF32 code points 来处理它们:

        public static IEnumerable<KeyValuePair<int, int>> Utf32IndexedCodePoints(this string s, int index)
        {
            for (int length = s.Length; index < length; index++)
            {
                yield return new KeyValuePair<int, int>(index, char.ConvertToUtf32(s, index));
                if (char.IsSurrogatePair(s, index))
                    index++;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 2012-06-22
      • 2021-12-05
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      相关资源
      最近更新 更多