// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
namespace EpicGames.Core
{
///
/// Extension methods for
///
public static class EnumerableExtensions
{
///
/// Dispose all elements in a sequence
///
/// Sequence of elements to dispose
public static void DisposeAll(this IEnumerable sequence)
{
foreach (IDisposable element in sequence)
{
element.Dispose();
}
}
///
/// Split the sequence into batches of at most the given size
///
/// The element type
/// Sequence to split into batches
/// Maximum size of each batch
/// Sequence of batches
public static IEnumerable> Batch(this IEnumerable sequence, int batchSize)
{
List elements = new List(batchSize);
foreach (TElement element in sequence)
{
elements.Add(element);
if (elements.Count == batchSize)
{
yield return elements;
elements.Clear();
}
}
if (elements.Count > 0)
{
yield return elements;
}
}
///
/// Finds the minimum element by a given field
///
///
///
///
///
public static TElement MinBy(this IEnumerable sequence, Func selector)
{
IEnumerator enumerator = sequence.GetEnumerator();
if (!enumerator.MoveNext())
{
throw new Exception("Collection is empty");
}
TElement minElement = enumerator.Current;
int minValue = selector(minElement);
while (enumerator.MoveNext())
{
int value = selector(enumerator.Current);
if (value < minValue)
{
minElement = enumerator.Current;
}
}
return minElement;
}
///
/// Finds the maximum element by a given field
///
///
///
///
///
public static TElement MaxBy(this IEnumerable sequence, Func selector)
{
IEnumerator enumerator = sequence.GetEnumerator();
if (!enumerator.MoveNext())
{
throw new Exception("Collection is empty");
}
TElement maxElement = enumerator.Current;
int maxValue = selector(maxElement);
while (enumerator.MoveNext())
{
int value = selector(enumerator.Current);
if (value > maxValue)
{
maxElement = enumerator.Current;
}
}
return maxElement;
}
///
/// Zips two dictionaries, returning a sequence of keys with the old and new values (or null if they have been removed).
///
/// Common key between the two dictionaries
/// Type of values in the first dictionary
/// Type of values in the second dictionary
/// The first dictionary
/// The second dictionary
/// Sequence of key/value pairs from each dictionary
public static IEnumerable<(TKey, TOldValue?, TNewValue?)> Zip(this IReadOnlyDictionary? oldDictionary, IReadOnlyDictionary? newDictionary)
where TKey : notnull
where TOldValue : class
where TNewValue : class
{
if (newDictionary != null)
{
foreach ((TKey key, TNewValue newValue) in newDictionary)
{
TOldValue? oldValue;
if (oldDictionary == null || !oldDictionary.TryGetValue(key, out oldValue))
{
yield return (key, null, newValue);
}
else
{
yield return (key, oldValue, newValue);
}
}
}
if (oldDictionary != null)
{
foreach ((TKey key, TOldValue oldValue) in oldDictionary)
{
if (newDictionary == null || !newDictionary.ContainsKey(key))
{
yield return (key, oldValue, null);
}
}
}
}
}
}