I have some trouble with executing an exercise from CodeWars. I made it in another compilator and everything works as it has to be but in CodeWars there are IEnumerable errors and I have no idea how to deal with them.
So, here is the exercise:
Implement the function
unique_in_order
which takes as argument a sequence and returns a list of items without any elements with the same value next to each other and preserving the original order of elements.For example:
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}
My solution:
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;
}
}
Errors I get:
src/Solution.cs(8,17): error CS0021: Cannot apply indexing with [] to an expression of type 'IEnumerable<T>'
src/Solution.cs(26,12): error CS0029: Cannot implicitly convert type 'string' to 'System.Collections.Generic.IEnumerable<T>'
Why don't you use yield return
keyword? They're handy.
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()));
}
}
Firstly, exchange var first = iterable[0];
with var first = iterable.First()
.
You can't use indexing on IEnumerable
.
Secondly you are using list of chars List<char>();
to store type T
. Use List<T>
.
You can't store general type as specific.
Thirdly, why you are using String.Join()
at the end, why not just return uniques?
List
is also an IEnumerable
.
You were close to a solution. Let's run through some errors:
In this statement: var first = iterable[0];
you can't access an IEnumerable item via indexing. IEnumerables aren't really lists or collections. I can expand on that if you'd like.
You could access it through:
var first = iterable.First();
In this statement: var uniques = new List<char>();
, you're creating a list of char to hold the itens of your IEnumerable, although the itens are of generic type T
. The correct form is:
var uniques = new List<T>();
In the line if (item == first)
, you can't compare two unconstrained generic types using ==
.
You can either use item.Equals(first)
or EqualityComparer<T>.Default.Equals(item, first)
.
Lastly, you're transforming your list in a string and returning it. Although the return type of your method is not a string, but rather an IEnumerable<T>
.
Instead of
var result = string.Join("", uniques);
return result;
You can get rid of result
, and return your list:
return uniques;
With these fixes, your code becomes:
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;
}
Which already works. However, this code could be simplified by removing the assignment of the first
variable and integrating it to a more general case. You could also remove the uniques
list and yield each item at a time.
My proposed final solution is as follows:
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;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.