我在执行CodeWars中的练习时遇到了一些问题。我在另一个编译程序中制作了它,一切都正常工作,但在CodeWars中存在IEnumerable错误,我不知道如何处理它们。
因此,以下是练习:
实现函数
unique_in_order
,该函数将序列,并返回一个不包含任何元素的项目列表彼此相邻的相同值,并保留的原始顺序元素。例如:
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<T>'
src/Solution.cs(26,12(:错误CS0029:无法将类型"string"隐式转换为"System.Collections.Generic.IEnumerable<T>'
为什么不使用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()));
}
}
您已接近解决方案。让我们来看看一些错误:
在以下语句中:var first = iterable[0];
您不能通过索引访问IEnumerable项。IEnumerables并不是真正的列表或集合。如果你愿意的话,我可以详述。
您可以通过以下途径访问:
var first = iterable.First();
在这个语句var uniques = new List<char>();
中,您创建了一个char列表来保存IEnumerable的iten,尽管iten是泛型类型T
。正确的形式是:
var uniques = new List<T>();
在if (item == first)
行中,不能使用==
比较两个不受约束的泛型类型。
您可以使用item.Equals(first)
或EqualityComparer<T>.Default.Equals(item, first)
。
最后,将列表转换为字符串并返回。尽管方法的返回类型不是字符串,而是IEnumerable<T>
。
代替
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;
}
}
首先,用var first = iterable.First()
交换var first = iterable[0];
不能在IEnumerable
上使用索引。
其次,您正在使用字符列表List<char>();
来存储类型T
。使用List<T>
不能将常规类型存储为特定类型。
第三,为什么最后使用String.Join()
,为什么不直接返回uniquesList
也是一个IEnumerable
。