I'd like to be able to write the following code:
// contains 500 entries
IList<string> longListOfStrings = ...
// shorterListsOfStrings is now an array of 5 IList<string>,
// with each element containing 100 strings
IList<string>[] shorterListsOfStrings = longListOfStrings.Split(5);
To do this I have to create a generic extension method called Split that looks something like the following:
public static TList[] Split<TList>(this TList source, int elementCount)
where TList : IList<>, ICollection<>, IEnumerable<>, IList, ICollection, IEnumerable
{
return null;
}
But when I try to compile that, the compiler tells me that IList<>, ICollection<> and IEnumerable<> require a type argument. So, I changed the definition to the following:
public static TList<TType>[] Split<TList<TType>>(this TList<TType> source, int elementCount)
where TList : IList<TType>, ICollection<TType>, IEnumerable<TType>, IList, ICollection, IEnumerable
{
return null;
}
but then the compiler complains that it can't find type TList. I have an idea that I'm overcomplicating things but I can't see how... any help is appreciated!
Yes, I think you're overcomplicating things. Try this:
public static IList<T>[] Split<T>(this IList<T> source, int elementCount)
{
// What the heck, it's easy to implement...
IList<T>[] ret = new IList<T>[(source.Count + elementCount - 1)
/ elementCount];
for (int i = 0; i < ret.Length; i++)
{
int start = i * elementCount;
int size = Math.Min(elementCount, source.Count - i * start);
T[] tmp = new T[size];
// Would like CopyTo with a count, but never mind
for (int j = 0; i < size; j++)
{
tmp[j] = source[j + start];
}
ret[i] = tmp;
}
return ret;
}
After all, you're not going to change which kind of list you create within the method based on the source, are you? You'll presumably create a List<T> (or maybe a T[]) even if I pass in some other implementation.
You might want to look at the Batch method in MoreLINQ for an IEnumerable<T>-based implementation.
How about this:
public static IList<TResult>[] Split<TSource, TResult>(
this IList<TSource> source, // input IList to split
Func<TSource, TResult> selector, // projection to apply to each item
int elementCount // number of items per IList
) {
// do something
}
And if you don't need a version to project each item:
public static IList<T>[] Split<T>(
this IList<T> source, // input IList to split
int elementCount // number of items per IList
) {
return Split<T, T>(source, x => x, elementCount);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With