using System;
using System.Collections.Generic;
using System.Linq;
namespace QFSW.QC.Utilities
{
public static class CollectionExtensions
{
/// Inverts the key/value relationship between the items in the dictionary.
/// Dictionary with the inverted relationship.
public static Dictionary Invert(this IDictionary source)
{
Dictionary dictionary = new Dictionary();
foreach (KeyValuePair item in source)
{
if (!dictionary.ContainsKey(item.Value))
{
dictionary.Add(item.Value, item.Key);
}
}
return dictionary;
}
/// Gets a sub array of an existing array.
/// Index to take the sub array from.
/// The length of the sub array.
public static T[] SubArray(this T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}
/// Skips the last element in the sequence.
public static IEnumerable SkipLast(this IEnumerable source)
{
using (IEnumerator enumurator = source.GetEnumerator())
{
if (enumurator.MoveNext())
{
for (T value = enumurator.Current; enumurator.MoveNext(); value = enumurator.Current)
{
yield return value;
}
}
}
}
/// Reverses the order of the sequence.
public static IEnumerable Reversed(this IReadOnlyList source)
{
for (int i = source.Count - 1; i >= 0; i--)
{
yield return source[i];
}
}
///
/// Creates a distinct stream based on a custom predicate.
///
/// The type of the IEnumerable.
/// The type of the value to test for distinctness.
/// The source IEnumerable.
/// The custom distinct item producer.
/// The distinct stream.
public static IEnumerable DistinctBy(this IEnumerable source, Func predicate)
{
HashSet set = new HashSet();
foreach (TValue value in source)
{
if (set.Add(predicate(value)))
{
yield return value;
}
}
}
public static IEnumerable Yield(this T item)
{
yield return item;
}
public static T LastOr(this IEnumerable source, T value)
{
try
{
return source.Last();
}
catch (InvalidOperationException)
{
return value;
}
}
public static unsafe void InsertionSortBy(this IList collection, Func keySelector)
{
const int maxStackSize = 512;
if (collection.Count <= maxStackSize)
{
int* keyBuffer = stackalloc int[collection.Count];
InsertionSortBy(collection, keySelector, keyBuffer);
}
else
{
int[] keyArray = new int[collection.Count];
fixed (int* keyBuffer = keyArray)
{
InsertionSortBy(collection, keySelector, keyBuffer);
}
}
}
private static unsafe void InsertionSortBy(this IList collection, Func keySelector, int* keyBuffer)
{
int n = collection.Count;
for (int i = 0; i < n; i++)
{
keyBuffer[i] = keySelector(collection[i]);
}
for (int i = 1; i < n; i++)
{
T item = collection[i];
int key = keyBuffer[i];
int j = i - 1;
while (j >= 0 && keyBuffer[j] > key)
{
collection[j + 1] = collection[j];
keyBuffer[j + 1] = keyBuffer[j];
j -= 1;
}
collection[j + 1] = item;
keyBuffer[j + 1] = key;
}
}
}
}