简体   繁体   English

从 IEnumerable 返回字符串<t> function</t>

[英]Returning a string from an IEnumerable<T>function

I am probably doing something wrong but I'm trying to do this Kata on Codewars我可能做错了什么,但我正在尝试在 Codewars 上做这个 Kata

This is my current code below.这是我下面的当前代码。

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();
 }
}

The unit tests for this kata are expecting an input of "AAAABBBCCDAABBB" to be returned as "ABCDAB".此 kata 的单元测试期望输入“AAAABBBCCDAABBB”作为“ABCDAB”返回。

My code above is failing due to this error Expected is <System.String>, actual is <System.Char[6]>由于此错误,我上面的代码失败Expected is <System.String>, actual is <System.Char[6]>

If I try to return a string I get this error: error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'如果我尝试返回一个字符串,我会收到此错误: error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'

I'm lost as how I can return the expected string if I can't return a string (and a char array fails)如果我无法返回字符串(并且 char 数组失败),我会迷失如何返回预期的字符串

Thanks谢谢

You can implement it like this (since you've used <T> let implement general case solution with custom comparer ):您可以像这样实现它(因为您已经使用<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;
    }
}

Here we just check if current item is equal to prior .这里我们只检查当前item是否等于prior项。

Demo:演示:

string source = "AAAABBBCCDAABBB";

string result = string.Concat(UniqueInOrder(source)); 

Console.Write(result);

Outcome:结果:

ABCDAB

Edit: Please, note that Distinct() in the编辑:请注意Distinct()

arr.Distinct()

removes duplicates in the entire arr , that's why you'll get only 4 distinct characters:删除整个arr中的重复项,这就是为什么你只会得到 4 个不同的字符:

AAAABBBCCDAABBB  ->  ABCD
             Distinct()

In the given problem we have a weaker condition: current item must not be equal to prior.在给定的问题中,我们有一个较弱的条件:当前项目不能等于先前项目。

This should do it:这应该这样做:

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
    }    
}

It uses a pattern of nested while loops called Control/Break that still runs in linear time (because only the inner loop advances).它使用一种称为Control/Break的嵌套 while 循环模式,该模式仍以线性时间运行(因为只有内部循环在前进)。

Here's a reduced version without the extra explainers:这是一个没有额外解释器的简化版本:

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()));
    }    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM