【问题标题】:Unique in order C#唯一的顺序 C#
【发布时间】:2021-07-11 09:06:25
【问题描述】:

我在执行 CodeWars 的练习时遇到了一些问题。我在另一个编译器中完成了它,一切正常,但在 CodeWars 中存在 IEnumerable 错误,我不知道如何处理它们。

所以,这是练习:

实现函数unique_in_order,它以a为参数 序列并返回没有任何元素的项目列表 相同的值彼此相邻并保留原始顺序 元素。

例如:

uniqueInOrder("AAAABBBCCDAABBB") == {'A', 'B', 'C', 'D', 'A', 'B'}
uniqueInOrder("ABBCcAD")         == {'A', 'B', 'C', 'c', 'A', 'D'}
uniqueInOrder([1,2,2,3,3])       == {1,2,3}

我的解决方案:

using System.Collections.Generic;

public static class Kata {
    public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable) {

    var first = iterable[0];
    
    var uniques = new List<char>();

    uniques.Add(first);
    
    foreach(var item in iterable)
    {
        if (item == first)
        {
            continue;
        }
        first = item;
        uniques.Add(first);
    }

    var result = string.Join("", uniques);

   return result;
  }
}

我得到的错误:

src/Solution.cs(8,17):错误 CS0021:无法使用 [] 将索引应用于“IEnumerable”类型的表达式
src/Solution.cs(26,12):错误 CS0029:无法将类型“字符串”隐式转换为“System.Collections.Generic.IEnumerable

【问题讨论】:

  • 如果您希望它在整数数组上工作,则不能使其成为 List (或字符串的返回类型)。使用 List 并返回它
  • var first = iterable[0]; - 你不能在这样的枚举中索引第一个项目。我很惊讶它在你的其他编译器中工作——哪一个?我认为T first = null;(或= default(T))和删除uniques.Add(first); 可以正常工作。
  • 尽管取决于测试用例的彻底程度,使用“第一个”布尔标志可能是最简单的,或者将 IEnumerable 解压缩到 IEnumerator 中并使用它来弹出列表的第一项。我也不认为您的返回字符串连接对于 int 列表和字符串情况都可以正常工作。您可能需要单独的字符串实现。
  • 我觉得你应该迭代 iterableyield return 任何你发现与前一个 T 不同的 T,除非你正在使用 "并返回一个列表项目”部分字面意思

标签: c# ienumerable


【解决方案1】:

为什么不使用yield return 关键字?它们很方便。

class Program
{
    public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> sequence)
    {
        T prev = default!;
        bool hasPrev = false;

        foreach (T item in sequence)
        {
            if ((!hasPrev && (hasPrev = true)) || !EqualityComparer<T>.Default.Equals(item, prev))
            {
                yield return item;
            }

            prev = item;
        }
    }

    static void Main(string[] args)
    {
        Console.WriteLine(new string(UniqueInOrder("AAAABBBCCDAABBB").ToArray()));
        Console.WriteLine(new string(UniqueInOrder("ABBCcAD").ToArray()));
    }
}

【讨论】:

    【解决方案2】:

    您已经接近解决方案。让我们来看看一些错误:

    在此语句中:var first = iterable[0]; 您无法通过索引访问 IEnumerable 项。 IEnumerables 并不是真正的列表或集合。如果您愿意,我可以对此进行扩展。

    您可以通过以下方式访问它:

    var first = iterable.First();
    

    在此语句中:var uniques = new List&lt;char&gt;();,您正在创建一个 char 列表来保存 IEnumerable 的元素,尽管这些元素是通用类型 T。正确的形式是:

    var uniques = new List<T>();
    

    if (item == first) 行中,您无法使用== 比较两个不受约束的泛型类型。

    您可以使用item.Equals(first)EqualityComparer&lt;T&gt;.Default.Equals(item, first)

    最后,您将列表转换为字符串并返回它。虽然你方法的返回类型不是字符串,而是IEnumerable&lt;T&gt;

    代替

     var result = string.Join("", uniques);
    
     return result;
    

    您可以摆脱result,并返回您的列表:

    return uniques;
    

    通过这些修复,您的代码变为:

    public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable) 
    {
        var first = iterable.First();
        
        var uniques = new List<T>();
    
        uniques.Add(first);
        
        foreach(var item in iterable)
        {
            if (item.Equals(first))
            {
                continue;
            }
            first = item;
            uniques.Add(item);
        }
    
        return uniques;
    }
    

    这已经有效。但是,可以通过删除first 变量的分配并将其集成到更一般的情况来简化此代码。您还可以删除 uniques 列表并一次生成每个项目。

    我提出的最终解决方案如下:

    public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable) 
    {
        var current = default(T);
        
        foreach(var item in iterable)
        {
            if (item.Equals(current))
                continue;
                
            current = item;
            
            yield return item;
        }
    }
    

    【讨论】:

    • 最后的建议是最佳实践之一,感谢分享
    【解决方案3】:

    首先将var first = iterable[0];换成var first = iterable.First()
    您不能在 IEnumerable 上使用索引。

    其次,您使用字符列表 List&lt;char&gt;(); 来存储类型T。使用List&lt;T&gt;
    您不能将一般类型存储为特定类型。

    第三,为什么你最后使用String.Join(),为什么不只返回唯一值?
    List 也是一个IEnumerable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-20
      • 2013-08-14
      • 1970-01-01
      • 2019-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-06
      相关资源
      最近更新 更多