从 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()

在给定的问题中,我们有一个 较弱的 条件:当前项不能等于先前项。