// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschränkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using System; using System.Collections.Generic; using System.Linq; namespace Squidex.Infrastructure { public static class CollectionExtensions { public static void AddRange(this ICollection target, IEnumerable source) { foreach (var value in source) { target.Add(value); } } public static IEnumerable Shuffle(this IEnumerable enumerable) { var random = new Random(); return enumerable.OrderBy(x => random.Next()).ToList(); } public static HashSet ToHashSet(this IEnumerable enumerable) { return new HashSet(enumerable); } public static IEnumerable OrEmpty(this IEnumerable source) { return source ?? Enumerable.Empty(); } public static IEnumerable Concat(this IEnumerable source, T value) { return source.Concat(Enumerable.Repeat(value, 1)); } public static TResult[] ToArray(this T[] value, Func convert) { var result = new TResult[value.Length]; for (var i = 0; i < value.Length; i++) { result[i] = convert(value[i]); } return result; } public static TResult[] ToArray(this IReadOnlyCollection value, Func convert) { var result = new TResult[value.Count]; var i = 0; foreach (var v in value) { result[i] = convert(v); i++; } return result; } public static int SequentialHashCode(this IEnumerable collection) { return collection.SequentialHashCode(EqualityComparer.Default); } public static int SequentialHashCode(this IEnumerable collection, IEqualityComparer comparer) { var hashCode = 17; foreach (var item in collection) { if (!Equals(item, null)) { hashCode = (hashCode * 23) + comparer.GetHashCode(item); } } return hashCode; } public static int OrderedHashCode(this IEnumerable collection) { return collection.OrderedHashCode(EqualityComparer.Default); } public static int OrderedHashCode(this IEnumerable collection, IEqualityComparer comparer) { Guard.NotNull(comparer, nameof(comparer)); var hashCodes = collection.Where(x => !Equals(x, null)).Select(x => x.GetHashCode()).OrderBy(x => x).ToArray(); var hashCode = 17; foreach (var code in hashCodes) { hashCode = (hashCode * 23) + code; } return hashCode; } public static int DictionaryHashCode(this IDictionary dictionary) { return DictionaryHashCode(dictionary, EqualityComparer.Default, EqualityComparer.Default); } public static int DictionaryHashCode(this IDictionary dictionary, IEqualityComparer keyComparer, IEqualityComparer valueComparer) { var hashCode = 17; foreach (var kvp in dictionary.OrderBy(x => x.Key)) { hashCode = (hashCode * 23) + keyComparer.GetHashCode(kvp.Key); if (!Equals(kvp.Value, null)) { hashCode = (hashCode * 23) + valueComparer.GetHashCode(kvp.Value); } } return hashCode; } public static bool EqualsDictionary(this IReadOnlyDictionary dictionary, IReadOnlyDictionary other) { return EqualsDictionary(dictionary, other, EqualityComparer.Default, EqualityComparer.Default); } public static bool EqualsDictionary(this IReadOnlyDictionary dictionary, IReadOnlyDictionary other, IEqualityComparer keyComparer, IEqualityComparer valueComparer) { var comparer = new KeyValuePairComparer(keyComparer, valueComparer); return other != null && dictionary.Count == other.Count && !dictionary.Except(other, comparer).Any(); } public static TValue GetOrDefault(this IReadOnlyDictionary dictionary, TKey key) { return dictionary.GetOrCreate(key, _ => default); } public static TValue GetOrAddDefault(this IDictionary dictionary, TKey key) { return dictionary.GetOrAdd(key, _ => default); } public static TValue GetOrNew(this IReadOnlyDictionary dictionary, TKey key) where TValue : class, new() { return dictionary.GetOrCreate(key, _ => new TValue()); } public static TValue GetOrAddNew(this IDictionary dictionary, TKey key) where TValue : class, new() { return dictionary.GetOrAdd(key, _ => new TValue()); } public static TValue GetOrCreate(this IReadOnlyDictionary dictionary, TKey key, Func creator) { if (!dictionary.TryGetValue(key, out var result)) { result = creator(key); } return result; } public static TValue GetOrAdd(this IDictionary dictionary, TKey key, TValue fallback) { if (!dictionary.TryGetValue(key, out var result)) { result = fallback; dictionary.Add(key, result); } return result; } public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func creator) { if (!dictionary.TryGetValue(key, out var result)) { result = creator(key); dictionary.Add(key, result); } return result; } public static TValue GetOrAdd(this IDictionary dictionary, TKey key, TContext context, Func creator) { if (!dictionary.TryGetValue(key, out var result)) { result = creator(key, context); dictionary.Add(key, result); } return result; } public static void Foreach(this IEnumerable collection, Action action) { foreach (var item in collection) { action(item); } } public sealed class KeyValuePairComparer : IEqualityComparer> { private readonly IEqualityComparer keyComparer; private readonly IEqualityComparer valueComparer; public KeyValuePairComparer(IEqualityComparer keyComparer, IEqualityComparer valueComparer) { this.keyComparer = keyComparer; this.valueComparer = valueComparer; } public bool Equals(KeyValuePair x, KeyValuePair y) { return keyComparer.Equals(x.Key, y.Key) && valueComparer.Equals(x.Value, y.Value); } public int GetHashCode(KeyValuePair obj) { return keyComparer.GetHashCode(obj.Key) ^ valueComparer.GetHashCode(obj.Value); } } } }