c#将字符串转换为IEnumerable <T>

1 c# string generics ienumerable casting

我有这个功能:

public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)  
{  
    return iterable.Distinct();  
}
Run Code Online (Sandbox Code Playgroud)

这适用于任何IEnumerable,除了字符串,我必须使用此调用测试它:

Assert.AreEqual("ABCDAB", UniqueInOrder("AAAABBBCCDAABBB"));
Run Code Online (Sandbox Code Playgroud)

断言失败:

Expected is <System.String>, actual is <System.Linq.Enumerable+<DistinctIterator>c__Iterator10`1[System.Char]>
  Values differ at index [4]
Run Code Online (Sandbox Code Playgroud)

我也试过类似的东西:

public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
    return "abc";
}
Run Code Online (Sandbox Code Playgroud)

但是我有一个编译器错误:

Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'
Run Code Online (Sandbox Code Playgroud)

怎么可能用字符串调用函数但我不能返回一个字符串?类型仍然是IEnumerable <T>

任何的想法?谢谢!

编辑:Distinct()错了,我改为:

public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable)
{
    List<T> result = new List<T>();
    foreach (var c in iterable.ToList())            
        if (result.LastOrDefault() == null || !result.LastOrDefault().Equals(c))
            result.Add(c);              
    return result;
}
Run Code Online (Sandbox Code Playgroud)

现在所有的测试都过去了!谢谢!

Him*_*ere 7

实际上字符串是一个字符集合,因此当你使用UniqueInOrder("AAAABBBCCDAABBB")你执行调用时UniqueInOrder<char>,而不是UniqueInOrder<string>.因此,方法的返回值也将是IEnumerble<char>,而不仅仅是字符串.

所以你应该将方法return-value与一组字符进行比较,例如:

CollectionAssert.AreEqual(new[] { 'A', 'B', 'C', 'D', 'A' 'B', 'Ä' }, UniqueInOrder(...));
Run Code Online (Sandbox Code Playgroud)

或更容易:

CollectionAssert.AreEqual(expected.ToCharArray(), UniqueInOrder(...));
Run Code Online (Sandbox Code Playgroud)

但即便如此,您的测试也会失败,因为Distinct会过滤掉所有重复项.

如果要检查两个序列是否完全相同,可以使用SequenceEqual:

var equal = firstColl.SequenceEqual(second);
Run Code Online (Sandbox Code Playgroud)

编辑:显然你试图删除所有序列中的双重字符.你可以用这个:

public static IEnumerable<T> UniqueInOrder<T>(IEnumerable<T> iterable) where T : IEquatable<T>
{
    T previous = default(T);
    foreach (var t in iterable)
    {
        if (!t.Equals(previous))
            yield return t;
        previous = t;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以调用它并将其与预期输出进行比较,例如:

var actual = new String(UniqueInOrder("AABBCCDDAABB").ToArray());
var expected "ABCDAB";
Assert.AreEqual(expected, actual);
Run Code Online (Sandbox Code Playgroud)