按C#顺序唯一



我在执行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(),为什么不直接返回uniques
List也是一个IEnumerable

最新更新