从 IEnumerable<T> 函数返回字符串
Returning a string from an IEnumerable<T>function
我可能做错了什么,但我正在尝试做 this Kata on Codewars
下面是我当前的代码。
public static class Kata
{
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> arr)
{
Type t = typeof(T);
if (t == typeof(string))
return (IEnumerable<T>)String.Join("",arr.Distinct()).AsEnumerable();
return arr.Distinct().ToArray();
}
}
此套路的单元测试期望输入“AAAABBCCDAABBB”return编辑为“ABCDAB”。
我上面的代码由于这个错误而失败
Expected is <System.String>, actual is <System.Char[6]>
如果我尝试 return 一个字符串,我会得到这个错误:error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'
如果我不能 return 一个字符串(并且字符数组失败),我怎么能 return 预期的字符串
谢谢
应该这样做:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext(); //start iterating
while (EnumeratorActive)
{
// set and yield the current value
T cur = e.Current;
yield return cur;
// keep advancing while the iterator is active and additional values match the current val
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()))
{} //empty body intentional
}
}
它使用称为 Control/Break 的嵌套 while 循环模式,它仍然以线性时间运行(因为只有内部循环前进)。
这是没有额外解释的简化版本:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext();
while (EnumeratorActive)
{
T cur = e.Current;
yield return cur;
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()));
}
}
你可以这样实现它(因为你已经使用了 <T>
让我们用自定义 comparer
实现 一般情况 解决方案):
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
comparer ??= EqualityComparer<T>.Default;
bool first = true;
T prior = default; // default: let compiler be happy
foreach (T item in source)
if (first || !comparer.Equals(item, prior)) {
prior = item;
first = false;
yield return item;
}
}
这里我们只是检查当前 item
是否等于 prior
.
演示:
string source = "AAAABBBCCDAABBB";
string result = string.Concat(UniqueInOrder(source));
Console.Write(result);
结果:
ABCDAB
编辑:请注意
中的Distinct()
arr.Distinct()
删除 整个 arr
中的重复项,这就是为什么你只会得到 4 个不同的字符:
AAAABBBCCDAABBB -> ABCD
Distinct()
在给定的问题中,我们有一个 较弱的 条件:当前项不能等于先前项。
我可能做错了什么,但我正在尝试做 this Kata on Codewars
下面是我当前的代码。
public static class Kata
{
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> arr)
{
Type t = typeof(T);
if (t == typeof(string))
return (IEnumerable<T>)String.Join("",arr.Distinct()).AsEnumerable();
return arr.Distinct().ToArray();
}
}
此套路的单元测试期望输入“AAAABBCCDAABBB”return编辑为“ABCDAB”。
我上面的代码由于这个错误而失败
Expected is <System.String>, actual is <System.Char[6]>
如果我尝试 return 一个字符串,我会得到这个错误:error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'
如果我不能 return 一个字符串(并且字符数组失败),我怎么能 return 预期的字符串
谢谢
应该这样做:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext(); //start iterating
while (EnumeratorActive)
{
// set and yield the current value
T cur = e.Current;
yield return cur;
// keep advancing while the iterator is active and additional values match the current val
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()))
{} //empty body intentional
}
}
它使用称为 Control/Break 的嵌套 while 循环模式,它仍然以线性时间运行(因为只有内部循环前进)。
这是没有额外解释的简化版本:
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
using var e = iterable.GetEnumerator();
bool EnumeratorActive = e.MoveNext();
while (EnumeratorActive)
{
T cur = e.Current;
yield return cur;
while(cur.Equals(e.Current) && (EnumeratorActive = e.MoveNext()));
}
}
你可以这样实现它(因为你已经使用了 <T>
让我们用自定义 comparer
实现 一般情况 解决方案):
public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
comparer ??= EqualityComparer<T>.Default;
bool first = true;
T prior = default; // default: let compiler be happy
foreach (T item in source)
if (first || !comparer.Equals(item, prior)) {
prior = item;
first = false;
yield return item;
}
}
这里我们只是检查当前 item
是否等于 prior
.
演示:
string source = "AAAABBBCCDAABBB";
string result = string.Concat(UniqueInOrder(source));
Console.Write(result);
结果:
ABCDAB
编辑:请注意
中的Distinct()
arr.Distinct()
删除 整个 arr
中的重复项,这就是为什么你只会得到 4 个不同的字符:
AAAABBBCCDAABBB -> ABCD
Distinct()
在给定的问题中,我们有一个 较弱的 条件:当前项不能等于先前项。