using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Kyoo
{
///
/// A set of extensions class for enumerable.
///
public static class EnumerableExtensions
{
///
/// A Select where the index of the item can be used.
///
/// The IEnumerable to map. If self is null, an empty list is returned
/// The function that will map each items
/// The type of items in
/// The type of items in the returned list
/// The list mapped or null if the input map was null.
/// mapper can't be null
public static IEnumerable Map([CanBeNull] this IEnumerable self,
[NotNull] Func mapper)
{
if (self == null)
return null;
if (mapper == null)
throw new ArgumentNullException(nameof(mapper));
static IEnumerable Generator(IEnumerable self, Func mapper)
{
using IEnumerator enumerator = self.GetEnumerator();
int index = 0;
while (enumerator.MoveNext())
{
yield return mapper(enumerator.Current, index);
index++;
}
}
return Generator(self, mapper);
}
///
/// A map where the mapping function is asynchronous.
/// Note: might interest you.
///
/// The IEnumerable to map. If self is null, an empty list is returned
/// The asynchronous function that will map each items
/// The type of items in
/// The type of items in the returned list
/// The list mapped as an AsyncEnumerable
/// mapper can't be null
public static async IAsyncEnumerable MapAsync([CanBeNull] this IEnumerable self,
[NotNull] Func> mapper)
{
if (self == null)
yield break;
if (mapper == null)
throw new ArgumentNullException(nameof(mapper));
using IEnumerator enumerator = self.GetEnumerator();
int index = 0;
while (enumerator.MoveNext())
{
yield return await mapper(enumerator.Current, index);
index++;
}
}
///
/// An asynchronous version of Select.
///
/// The IEnumerable to map
/// The asynchronous function that will map each items
/// The type of items in
/// The type of items in the returned list
/// The list mapped as an AsyncEnumerable
/// mapper can't be null
public static async IAsyncEnumerable SelectAsync([CanBeNull] this IEnumerable self,
[NotNull] Func> mapper)
{
if (self == null)
yield break;
if (mapper == null)
throw new ArgumentNullException(nameof(mapper));
using IEnumerator enumerator = self.GetEnumerator();
while (enumerator.MoveNext())
yield return await mapper(enumerator.Current);
}
///
/// Convert an AsyncEnumerable to a List by waiting for every item.
///
/// The async list
/// The type of items in the async list and in the returned list.
/// A task that will return a simple list
/// The list can't be null
public static async Task> ToListAsync([NotNull] this IAsyncEnumerable self)
{
if (self == null)
throw new ArgumentNullException(nameof(self));
List ret = new();
await foreach(T i in self)
ret.Add(i);
return ret;
}
///
/// If the enumerable is empty, execute an action.
///
/// The enumerable to check
/// The action to execute is the list is empty
/// The type of items inside the list
///
public static IEnumerable IfEmpty(this IEnumerable self, Action action)
{
using IEnumerator enumerator = self.GetEnumerator();
if (!enumerator.MoveNext())
{
action();
yield break;
}
do
{
yield return enumerator.Current;
}
while (enumerator.MoveNext());
}
///
/// A foreach used as a function with a little specificity: the list can be null.
///
/// The list to enumerate. If this is null, the function result in a no-op
/// The action to execute for each arguments
/// The type of items in the list
public static void ForEach([CanBeNull] this IEnumerable self, Action action)
{
if (self == null)
return;
foreach (T i in self)
action(i);
}
///
/// A foreach used as a function with a little specificity: the list can be null.
///
/// The list to enumerate. If this is null, the function result in a no-op
/// The action to execute for each arguments
public static void ForEach([CanBeNull] this IEnumerable self, Action