【问题标题】:Find the first distinct character in an array of characters and its index查找字符数组中的第一个不同字符及其索引
【发布时间】:2019-11-24 18:13:31
【问题描述】:

给定一个字符数组,我正在寻找找到第一个不同字符及其在数组中的索引的最佳方法。这段代码似乎可以完成这项工作,但我想知道是否有更好的方法可以在没有这么多循环的情况下完成它。感谢您的意见!

static string firstDistinctChar(char[] myChars)
    {
        string result = "No Distinct Chars found!";

        Dictionary<char, int> charDict = new Dictionary<char, int>();
        for (int i = 0; i < myChars.Length; i++)
        {//create dictionary of char and counts of char in array
            if (charDict.TryGetValue(myChars[i], out int count))
            {
                charDict[myChars[i]] = count + 1;
            }
            else
            {
                charDict.Add(myChars[i], 1);
            }
        }
        foreach (var item in charDict)
        {
            //remove all non distinct chars from dictionary
            if (item.Value > 1) { charDict.Remove(item.Key); }
        }
        for (int i = 0; i < myChars.Length; i++)
        {
            //loop thru each char in array and return first matching char and index
            if (charDict.TryGetValue(myChars[i], out _))
            {
                result = string.Format("The char: {0} is the first distinct char in the array with an index of : {1}", myChars[i], i);
                return result;
            }
        }
        return result;
    }

【问题讨论】:

    标签: c# arrays dictionary for-loop refactoring


    【解决方案1】:

    使用 linq 可以将其缩短很多。

    void Main()
    {
        var z = firstDistinctChar("AABBCCddefg".ToCharArray());
        Console.WriteLine(z);
    
    }
    static string firstDistinctChar(char[] myChars)
    {
        // Group chars in the array then take groups with count = 1 and extract only the first group 
        var group = myChars.GroupBy(c => c).Where(c => c.Count() == 1).FirstOrDefault();
        if (group != null)
        {
           // From the first group extract the first (and only) value
           char u = group.First();
    
           // Now find the position of the distinct char 
           // creating a new array until we reach the distinct character 
           int i = myChars.TakeWhile(c => c != u).Count();
    
           return string.Format("The char: {0} is the first distinct char in the array at index {1}", u,i);
        }
        else
           return "No Distinct Chars found!";
    }
    

    这是有效的,因为根据this answer

    GroupBy - IGrouping 对象的生成顺序基于 source 中产生每个元素的第一个键的元素的顺序 分组。分组中的元素按照它们出现的顺序产生 在源代码中。

    这是否比您当前的解决方案更好?我相信这会更短,但就性能而言,它应该用你的实际数据进行测试,没有适当的 cmets 有点晦涩

    【讨论】:

    • 谢谢!你的跑得更快!没有 cmets 有点晦涩难懂。感谢您提供 IGrouping 信息。
    【解决方案2】:

    我想知道是否有没有这么多循环的更好方法。


    我会做出的最大改变是

    1. 删除第二个循环。
    2. 使用最后一个循环检查字符数是否为 1,这就是允许删除第二个循环的原因。

    其他 cmets 只是我的 2 美分。

    static string FirstDistinctChar(char[] myChars)
    {
        // You'll want to decide what to do if your parameter is null.
                
        Dictionary<char, int> charDict = new Dictionary<char, int>();
    
        // You're iterating thru every element, you don't need the index value, 
        // and you're not changing the collection, so use foreach instead of for.
        // foreach is preferred for readability and maintainability.
        foreach (char c in myChars)
        {
            if (charDict.TryGetValue(c, out int count))
            {
                charDict[c] = count + 1;
            }
            else
            {
                charDict.Add(c, 1);
            }
        }
                
        // It's not necessary to remove non-distinct chars from charDict;
        // just check for a value of 1. This allows the removal of a loop from your code. :-)
        for (int i = 0; i < myChars.Length; ++i)
        {
            if (charDict[myChars[i]] == 1)
            {
                // Placeholders are difficult to read. I use string interpolation (c# 6 and up).
                return $"The char {myChars[i]} is the first distinct char in the array with an index of {i}";
            }
        }
    
        return "No distinct chars found.";
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-29
      • 2012-05-02
      • 1970-01-01
      • 2017-02-23
      • 2023-03-10
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 2011-11-20
      相关资源
      最近更新 更多