using System.Collections.Generic;
using System;
using System.Linq;
namespace Barotrauma.Extensions
{
public static class IEnumerableExtensions
{
///
/// Randomizes the collection (using OrderBy) and returns it.
///
public static IOrderedEnumerable Randomize(this IEnumerable source, Rand.RandSync randSync = Rand.RandSync.Unsynced)
{
return source.OrderBy(i => Rand.Value(randSync));
}
///
/// Randomizes the list in place without creating a new collection, using a Fisher-Yates-based algorithm.
///
public static void Shuffle(this IList list, Rand.RandSync randSync = Rand.RandSync.Unsynced)
{
int n = list.Count;
while (n > 1)
{
n--;
int k = Rand.Int(n + 1, randSync);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
}
public static T GetRandom(this IEnumerable source, Func predicate, Rand.RandSync randSync = Rand.RandSync.Unsynced)
{
if (predicate == null) { return GetRandom(source, randSync); }
return source.Where(predicate).GetRandom(randSync);
}
public static T GetRandom(this IEnumerable source, Rand.RandSync randSync = Rand.RandSync.Unsynced)
{
if (source is IList list)
{
int count = list.Count;
return count == 0 ? default : list[Rand.Range(0, count, randSync)];
}
else
{
int count = source.Count();
return count == 0 ? default : source.ElementAt(Rand.Range(0, count, randSync));
}
}
public static T GetRandom(this IEnumerable source, Random random)
{
if (source is IList list)
{
int count = list.Count;
return count == 0 ? default : list[random.Next(0, count)];
}
else
{
int count = source.Count();
return count == 0 ? default : source.ElementAt(random.Next(0, count));
}
}
public static T RandomElementByWeight(this IEnumerable source, Func weightSelector, Rand.RandSync randSync = Rand.RandSync.Unsynced)
{
float totalWeight = source.Sum(weightSelector);
float itemWeightIndex = Rand.Range(0f, 1f, randSync) * totalWeight;
float currentWeightIndex = 0;
foreach (T weightedItem in source)
{
float weight = weightSelector(weightedItem);
currentWeightIndex += weight;
if (currentWeightIndex >= itemWeightIndex)
{
return weightedItem;
}
}
return default;
}
///
/// Executes an action that modifies the collection on each element (such as removing items from the list).
/// Creates a temporary list.
///
public static void ForEachMod(this IEnumerable source, Action action)
{
var temp = new List(source);
temp.ForEach(action);
}
///
/// Generic version of List.ForEach.
/// Performs the specified action on each element of the collection (short hand for a foreach loop).
///
public static void ForEach(this IEnumerable source, Action action)
{
foreach (var item in source)
{
action(item);
}
}
///
/// Shorthand for !source.Any(predicate) -> i.e. not any.
///
public static bool None(this IEnumerable source, Func predicate = null)
{
if (predicate == null)
{
return !source.Any();
}
else
{
return !source.Any(predicate);
}
}
public static bool Multiple(this IEnumerable source, Func predicate = null)
{
if (predicate == null)
{
return source.Count() > 1;
}
else
{
return source.Count(predicate) > 1;
}
}
public static IEnumerable ToEnumerable(this T item)
{
yield return item;
}
// source: https://stackoverflow.com/questions/19237868/get-all-children-to-one-list-recursive-c-sharp
public static IEnumerable SelectManyRecursive(this IEnumerable source, Func> selector)
{
var result = source.SelectMany(selector);
if (!result.Any())
{
return result;
}
return result.Concat(result.SelectManyRecursive(selector));
}
public static void AddIfNotNull(this IList source, T value)
{
if (value != null) { source.Add(value); }
}
}
}