//******************************************************************************************************// CollectionExtensions.cs - Gbtc//// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://www.opensource.org/licenses/MIT//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 02/23/2003 - J. Ritchie Carroll// Generated original version of source code.// 01/23/2005 - J. Ritchie Carroll// Migrated 2.0 version of source code from 1.1 source (GSF.Shared.Common).// 08/17/2007 - Darrell Zuercher// Edited code comments.// 09/11/2008 - J. Ritchie Carroll// Converted to C# extension functions.// 02/17/2009 - Josh L. Patterson// Edited Code Comments.// 02/20/2009 - J. Ritchie Carroll// Added predicate based IndexOf that extends IList<T>.// 04/02/2009 - J. Ritchie Carroll// Added seed based scramble and unscramble IList<T> extensions.// 06/05/2009 - Pinal C. Patel// Added generic AddRange() extension method for IList<T>.// 06/09/2009 - Pinal C. Patel// Added generic GetRange() extension method for IList<T>.// 08/05/2009 - Josh L. Patterson// Update comments.// 09/14/2009 - Stephen C. Wills// Added new header and license agreement.// 11/17/2009 - Pinal C. Patel// Added generic UpdateRange() extension method for IList<T>.// 03/31/2009 - J. Ritchie Carroll// Added Majority() and Minority() extension methods to IEnumerable<T>.// 03/18/2011 - J. Ritchie Carroll// Added dictionary Merge() extensions method for IDictionary and Any/All extensions for BitArray.// 03/22/2011 - J. Ritchie Carroll// Modified array copy extension to handle zero length (i.e., empty) source arrays.// 10/17/2011 - J. Ritchie Carroll// Added the ability to specify a default value for Majority and Minority when none exists.// 12/13/2012 - Starlynn Danyelle Gilliam// Modified Header.// 03/13/2016 - J. Ritchie Carroll// Added ToPagedList extension for enumerations.////****************************************************************************************************** using System;using System.Collections;using System.Collections.Generic;using System.Collections.Specialized;using System.Linq;using System.Text;using Random = GSF.Security.Cryptography.Random; namespace GSF.Collections{ /// <summary> /// Defines extension functions related to manipulation of arrays and collections. /// </summary> public static class CollectionExtensions { /// <summary> /// Gets a <see cref="PagedList{T}"/> to paginate <paramref name="source"/> enumeration for /// a given <paramref name="page"/> and specified <paramref name="pageSize"/>. /// </summary> /// <typeparam name="T">Type of <see cref="IEnumerable{T}"/> to paginate.</typeparam> /// <param name="source">Source enumeration to paginate.</param> /// <param name="page">Page number (1-based).</param> /// <param name="pageSize">Page size.</param> /// <returns>Set of items on a given <paramref name="page"/> for specified <paramref name="pageSize"/>.</returns> public static PagedList<T> ToPagedList<T>(this IEnumerable<T> source, int page, int pageSize) { return new PagedList<T>(source, page, pageSize); } /// <summary> /// Merges elements of multiple dictionaries into a single dictionary with no duplicate key values overwritten. /// </summary> /// <typeparam name="T">Type of <see cref="IDictionary{TKey, TValue}"/> to merge.</typeparam> /// <typeparam name="TKey">Type of <see cref="IDictionary{TKey, TValue}"/> keys.</typeparam> /// <typeparam name="TValue">Type of <see cref="IDictionary{TKey, TValue}"/> values.</typeparam> /// <param name="source">Source dictionary to merge with another dictionary.</param> /// <param name="others">Other dictionaries to merge with source dictionary.</param> /// <returns> /// A merged collection of all unique dictionary elements, all <paramref name="others"/> merged left to the source with no duplicate /// key values overwritten (i.e., first encountered key value pair is the one that remains in the returned merged dictionary). /// </returns> public static T Merge<T, TKey, TValue>(this T source, params IDictionary<TKey, TValue>[] others) where T : IDictionary<TKey, TValue>, new() { return source.Merge(false, others); } /// <summary> /// Merges elements of multiple dictionaries into a single dictionary. /// </summary> /// <typeparam name="T">Type of <see cref="IDictionary{TKey, TValue}"/> to merge.</typeparam> /// <typeparam name="TKey">Type of <see cref="IDictionary{TKey, TValue}"/> keys.</typeparam> /// <typeparam name="TValue">Type of <see cref="IDictionary{TKey, TValue}"/> values.</typeparam> /// <param name="source">Source dictionary to merge with another dictionary.</param> /// <param name="overwriteExisting">Set to <c>true</c> to overwrite duplicate key values as they are encountered.</param> /// <param name="others">Other dictionaries to merge with source dictionary.</param> /// <returns>A merged collection of all unique dictionary elements, all <paramref name="others"/> merged left to the source.</returns> public static T Merge<T, TKey, TValue>(this T source, bool overwriteExisting, params IDictionary<TKey, TValue>[] others) where T : IDictionary<TKey, TValue>, new() { T mergedDictionary = new T(); List<IDictionary<TKey, TValue>> allDictionaries = new List<IDictionary<TKey, TValue>>(); allDictionaries.Add(source); allDictionaries.AddRange(others); foreach (IDictionary<TKey, TValue> dictionary in allDictionaries) { foreach (KeyValuePair<TKey, TValue> kvPair in dictionary) { if (overwriteExisting) { mergedDictionary[kvPair.Key] = kvPair.Value; } else { if (!mergedDictionary.ContainsKey(kvPair.Key)) mergedDictionary.Add(kvPair); } } } return mergedDictionary; } /// <summary> /// Attempts to get the value for the given key and returns the default value instead if the key does not exist in the <see cref="IDictionary{TKey, TValue}"/>. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to check for the given key.</param> /// <param name="key">The key to be checked for the existence of a value.</param> /// <returns>The value of the key in the dictionary or the default value if no such value exists.</returns> public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) { return dictionary.GetOrDefault(key, k => default(TValue)); } /// <summary> /// Attempts to get the value for the given key and returns the default value instead if the key does not exist in the <see cref="IDictionary{TKey, TValue}"/>. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to check for the given key.</param> /// <param name="key">The key to be checked for the existence of a value.</param> /// <param name="defaultValueFactory">The function used to generate the default value if no value exists for the given key.</param> /// <returns>The value of the key in the dictionary or the default value if no such value exists.</returns> public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> defaultValueFactory) { TValue value; if (!dictionary.TryGetValue(key, out value)) value = defaultValueFactory(key); return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added to the dictionary if it does not already exist.</param> /// <param name="valueFactory">The function used to generate a value for the key.</param> /// <returns>The value of the key in the dictionary.</returns> public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory) { TValue value; if (!dictionary.TryGetValue(key, out value)) { value = valueFactory(key); dictionary.Add(key, value); } return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added to the dictionary if it does not already exist.</param> /// <param name="value">The value to assign to the key if the key does not already exist.</param> /// <returns>The value of the key in the dictionary.</returns> public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) { TValue tryGetValue; if (!dictionary.TryGetValue(key, out tryGetValue)) { tryGetValue = value; dictionary.Add(key, tryGetValue); } return tryGetValue; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or whose value should be updated</param> /// <param name="addValueFactory">The function used to generate a value for an absent key</param> /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param> /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was absent) or the result of updateValueFactory (if the key was present).</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) { TValue value; if (dictionary.TryGetValue(key, out value)) value = updateValueFactory(key, value); else value = addValueFactory(key); dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or whose value should be updated</param> /// <param name="addValue">The value to be added for an absent key</param> /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param> /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was absent) or the result of updateValueFactory (if the key was present).</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory) { TValue value; if (dictionary.TryGetValue(key, out value)) value = updateValueFactory(key, value); else value = addValue; dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or updated.</param> /// <param name="valueFactory">The function used to generate a value for the key.</param> /// <returns>The value of the key in the dictionary after updating.</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory) { TValue value = valueFactory(key); dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or updated.</param> /// <param name="value">The value to be assigned to the key.</param> /// <returns>The value of the key in the dictionary after updating.</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) { dictionary[key] = value; return value; } /// <summary> /// Converts a name/value collection to a dictionary. /// </summary> /// <param name="collection">Name/value collection.</param> /// <returns>Dictionary converted from a name/value collection.</returns> public static Dictionary<string, string> ToDictionary(this NameValueCollection collection) { return collection.AllKeys.ToDictionary(key => key, key => collection[key]); } /// <summary> /// Returns <c>true</c> if any item in <see cref="BitArray"/> is equal to <paramref name="value"/>. /// </summary> /// <param name="source">Source <see cref="BitArray"/>.</param> /// <param name="value"><see cref="bool"/> value to test for.</param> /// <returns><c>true</c> if any item in <see cref="BitArray"/> is equal to <paramref name="value"/>.</returns> public static bool Any(this BitArray source, bool value) { return source.Cast<bool>().Any(item => item == value); } /// <summary> /// Returns <c>true</c> if all items in <see cref="BitArray"/> are equal to <paramref name="value"/>. /// </summary> /// <param name="source">Source <see cref="BitArray"/>.</param> /// <param name="value"><see cref="bool"/> value to test for.</param> /// <returns><c>true</c> if all items in <see cref="BitArray"/> are equal to <paramref name="value"/>.</returns> public static bool All(this BitArray source, bool value) { return source.Cast<bool>().All(item => item == value); } /// <summary> /// Returns the majority value in the collection, or default type value if no item represents the majority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the majority element.</param> /// <returns>The majority value in the collection.</returns> public static T Majority<T>(this IEnumerable<T> source) { return source.Majority(default(T)); } /// <summary> /// Returns the majority value in the collection, or <paramref name="defaultValue"/> if no item represents the majority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the majority element.</param> /// <param name="defaultValue">Default value to return if no item represents the majority.</param> /// <returns>The majority value in the collection.</returns> public static T Majority<T>(this IEnumerable<T> source, T defaultValue) { T majority = defaultValue; if ((object)source == null) return majority; if (source.Count() > 1) { Dictionary<T, int> itemCounts = new Dictionary<T, int>(); int count; // Count each number of items in the list foreach (T item in source) { if (itemCounts.TryGetValue(item, out count)) { count++; itemCounts[item] = count; } else { itemCounts.Add(item, 1); } } // Find the largest number of items in the list KeyValuePair<T, int> maxItem = itemCounts.Max((a, b) => (a.Value < b.Value ? -1 : (a.Value > b.Value ? 1 : 0))); // If item with largest count has a plural majority, then it is the majority item if (maxItem.Value > 1) majority = maxItem.Key; } else { majority = source.FirstOrDefault(); } return majority; } /// <summary> /// Returns the minority value in the collection, or default type value if no item represents the minority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the minority element.</param> /// <returns>The minority value in the collection.</returns> public static T Minority<T>(this IEnumerable<T> source) { return source.Minority(default(T)); } /// <summary> /// Returns the minority value in the collection, or <paramref name="defaultValue"/> if no item represents the minority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the minority element.</param> /// <param name="defaultValue">Default value to return if no item represents the minority.</param> /// <returns>The minority value in the collection.</returns> public static T Minority<T>(this IEnumerable<T> source, T defaultValue) { T minority = defaultValue; if ((object)source == null) return minority; if (source.Count() > 1) { Dictionary<T, int> itemCounts = new Dictionary<T, int>(); int count; // Count each number of items in the list foreach (T item in source) { if (itemCounts.TryGetValue(item, out count)) { count++; itemCounts[item] = count; } else { itemCounts.Add(item, 1); } } // Find the smallest number of items in the list KeyValuePair<T, int> minItem = itemCounts.Min((a, b) => (a.Value < b.Value ? -1 : (a.Value > b.Value ? 1 : 0))); minority = minItem.Key; } else { minority = source.FirstOrDefault(); } return minority; } /// <summary> /// Adds the specified <paramref name="items"/> to the <paramref name="collection"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection to which the <paramref name="items"/> are to be added.</param> /// <param name="items">The elements to be added to the <paramref name="collection"/>.</param> public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items) { foreach (T item in items) { collection.Add(item); } } /// <summary> /// Updates <paramref name="collection"/> starting at the <paramref name="index"/> with the specified <paramref name="items"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection whose elements are to be updated with the specified <paramref name="items"/>.</param> /// <param name="index">The zero-based index in the <paramref name="collection"/> at which elements are to be updated.</param> /// <param name="items">The elements that will replace the <paramref name="collection"/> elements starting at the <paramref name="index"/>.</param> /// <exception cref="ArgumentOutOfRangeException">The specified <paramref name="index"/> is present in the <paramref name="collection"/>.</exception> public static void UpdateRange<T>(this IList<T> collection, int index, IEnumerable<T> items) { foreach (T item in items) { collection[index++] = item; } } /// <summary> /// Returns elements in the specified range from the <paramref name="collection"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection from which elements are to be retrieved.</param> /// <param name="index">The 0-based index position in the <paramref name="collection"/> from which elements are to be retrieved.</param> /// <param name="count">The number of elements to be retrieved from the <paramref name="collection"/> starting at the <paramref name="index"/>.</param> /// <returns>An <see cref="IList{T}"/> object.</returns> public static IList<T> GetRange<T>(this IList<T> collection, int index, int count) { List<T> result = new List<T>(); for (int i = index; i < index + count; i++) { result.Add(collection[i]); } return result; } /// <summary> /// Returns the index of the first element of the sequence that satisfies a condition or <c>-1</c> if no such element is found. /// </summary> /// <param name="source">A <see cref="IList{T}"/> to find an index in.</param> /// <param name="predicate">A function to test each element for a condition.</param> /// <returns>Index of the first element in <paramref name="source"/> that matches the specified <paramref name="predicate"/>; otherwise, <c>-1</c>.</returns> /// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam> public static int IndexOf<T>(this IList<T> source, Func<T, bool> predicate)Lines 1–500 of 1036. Load more
//****************************************************************************************************** // CollectionExtensions.cs - Gbtc // // Copyright © 2012, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 02/23/2003 - J. Ritchie Carroll // Generated original version of source code. // 01/23/2005 - J. Ritchie Carroll // Migrated 2.0 version of source code from 1.1 source (GSF.Shared.Common). // 08/17/2007 - Darrell Zuercher // Edited code comments. // 09/11/2008 - J. Ritchie Carroll // Converted to C# extension functions. // 02/17/2009 - Josh L. Patterson // Edited Code Comments. // 02/20/2009 - J. Ritchie Carroll // Added predicate based IndexOf that extends IList<T>. // 04/02/2009 - J. Ritchie Carroll // Added seed based scramble and unscramble IList<T> extensions. // 06/05/2009 - Pinal C. Patel // Added generic AddRange() extension method for IList<T>. // 06/09/2009 - Pinal C. Patel // Added generic GetRange() extension method for IList<T>. // 08/05/2009 - Josh L. Patterson // Update comments. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 11/17/2009 - Pinal C. Patel // Added generic UpdateRange() extension method for IList<T>. // 03/31/2009 - J. Ritchie Carroll // Added Majority() and Minority() extension methods to IEnumerable<T>. // 03/18/2011 - J. Ritchie Carroll // Added dictionary Merge() extensions method for IDictionary and Any/All extensions for BitArray. // 03/22/2011 - J. Ritchie Carroll // Modified array copy extension to handle zero length (i.e., empty) source arrays. // 10/17/2011 - J. Ritchie Carroll // Added the ability to specify a default value for Majority and Minority when none exists. // 12/13/2012 - Starlynn Danyelle Gilliam // Modified Header. // 03/13/2016 - J. Ritchie Carroll // Added ToPagedList extension for enumerations. // //****************************************************************************************************** using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Text; using Random = GSF.Security.Cryptography.Random; namespace GSF.Collections { /// <summary> /// Defines extension functions related to manipulation of arrays and collections. /// </summary> public static class CollectionExtensions { /// <summary> /// Gets a <see cref="PagedList{T}"/> to paginate <paramref name="source"/> enumeration for /// a given <paramref name="page"/> and specified <paramref name="pageSize"/>. /// </summary> /// <typeparam name="T">Type of <see cref="IEnumerable{T}"/> to paginate.</typeparam> /// <param name="source">Source enumeration to paginate.</param> /// <param name="page">Page number (1-based).</param> /// <param name="pageSize">Page size.</param> /// <returns>Set of items on a given <paramref name="page"/> for specified <paramref name="pageSize"/>.</returns> public static PagedList<T> ToPagedList<T>(this IEnumerable<T> source, int page, int pageSize) { return new PagedList<T>(source, page, pageSize); } /// <summary> /// Merges elements of multiple dictionaries into a single dictionary with no duplicate key values overwritten. /// </summary> /// <typeparam name="T">Type of <see cref="IDictionary{TKey, TValue}"/> to merge.</typeparam> /// <typeparam name="TKey">Type of <see cref="IDictionary{TKey, TValue}"/> keys.</typeparam> /// <typeparam name="TValue">Type of <see cref="IDictionary{TKey, TValue}"/> values.</typeparam> /// <param name="source">Source dictionary to merge with another dictionary.</param> /// <param name="others">Other dictionaries to merge with source dictionary.</param> /// <returns> /// A merged collection of all unique dictionary elements, all <paramref name="others"/> merged left to the source with no duplicate /// key values overwritten (i.e., first encountered key value pair is the one that remains in the returned merged dictionary). /// </returns> public static T Merge<T, TKey, TValue>(this T source, params IDictionary<TKey, TValue>[] others) where T : IDictionary<TKey, TValue>, new() { return source.Merge(false, others); } /// <summary> /// Merges elements of multiple dictionaries into a single dictionary. /// </summary> /// <typeparam name="T">Type of <see cref="IDictionary{TKey, TValue}"/> to merge.</typeparam> /// <typeparam name="TKey">Type of <see cref="IDictionary{TKey, TValue}"/> keys.</typeparam> /// <typeparam name="TValue">Type of <see cref="IDictionary{TKey, TValue}"/> values.</typeparam> /// <param name="source">Source dictionary to merge with another dictionary.</param> /// <param name="overwriteExisting">Set to <c>true</c> to overwrite duplicate key values as they are encountered.</param> /// <param name="others">Other dictionaries to merge with source dictionary.</param> /// <returns>A merged collection of all unique dictionary elements, all <paramref name="others"/> merged left to the source.</returns> public static T Merge<T, TKey, TValue>(this T source, bool overwriteExisting, params IDictionary<TKey, TValue>[] others) where T : IDictionary<TKey, TValue>, new() { T mergedDictionary = new T(); List<IDictionary<TKey, TValue>> allDictionaries = new List<IDictionary<TKey, TValue>>(); allDictionaries.Add(source); allDictionaries.AddRange(others); foreach (IDictionary<TKey, TValue> dictionary in allDictionaries) { foreach (KeyValuePair<TKey, TValue> kvPair in dictionary) { if (overwriteExisting) { mergedDictionary[kvPair.Key] = kvPair.Value; } else { if (!mergedDictionary.ContainsKey(kvPair.Key)) mergedDictionary.Add(kvPair); } } } return mergedDictionary; } /// <summary> /// Attempts to get the value for the given key and returns the default value instead if the key does not exist in the <see cref="IDictionary{TKey, TValue}"/>. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to check for the given key.</param> /// <param name="key">The key to be checked for the existence of a value.</param> /// <returns>The value of the key in the dictionary or the default value if no such value exists.</returns> public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key) { return dictionary.GetOrDefault(key, k => default(TValue)); } /// <summary> /// Attempts to get the value for the given key and returns the default value instead if the key does not exist in the <see cref="IDictionary{TKey, TValue}"/>. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to check for the given key.</param> /// <param name="key">The key to be checked for the existence of a value.</param> /// <param name="defaultValueFactory">The function used to generate the default value if no value exists for the given key.</param> /// <returns>The value of the key in the dictionary or the default value if no such value exists.</returns> public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> defaultValueFactory) { TValue value; if (!dictionary.TryGetValue(key, out value)) value = defaultValueFactory(key); return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added to the dictionary if it does not already exist.</param> /// <param name="valueFactory">The function used to generate a value for the key.</param> /// <returns>The value of the key in the dictionary.</returns> public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory) { TValue value; if (!dictionary.TryGetValue(key, out value)) { value = valueFactory(key); dictionary.Add(key, value); } return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added to the dictionary if it does not already exist.</param> /// <param name="value">The value to assign to the key if the key does not already exist.</param> /// <returns>The value of the key in the dictionary.</returns> public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) { TValue tryGetValue; if (!dictionary.TryGetValue(key, out tryGetValue)) { tryGetValue = value; dictionary.Add(key, tryGetValue); } return tryGetValue; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or whose value should be updated</param> /// <param name="addValueFactory">The function used to generate a value for an absent key</param> /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param> /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was absent) or the result of updateValueFactory (if the key was present).</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) { TValue value; if (dictionary.TryGetValue(key, out value)) value = updateValueFactory(key, value); else value = addValueFactory(key); dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or whose value should be updated</param> /// <param name="addValue">The value to be added for an absent key</param> /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on the key's existing value</param> /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was absent) or the result of updateValueFactory (if the key was present).</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory) { TValue value; if (dictionary.TryGetValue(key, out value)) value = updateValueFactory(key, value); else value = addValue; dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or updated.</param> /// <param name="valueFactory">The function used to generate a value for the key.</param> /// <returns>The value of the key in the dictionary after updating.</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory) { TValue value = valueFactory(key); dictionary[key] = value; return value; } /// <summary> /// Adds a key/value pair to the <see cref="IDictionary{TKey, TValue}"/> if the key does not already exist, /// or updates a key/value pair in the <see cref="IDictionary{TKey, TValue}"/> if the key already exists. /// </summary> /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam> /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam> /// <param name="dictionary">The dictionary to add the key/value pair to if the key does not already exist.</param> /// <param name="key">The key to be added or updated.</param> /// <param name="value">The value to be assigned to the key.</param> /// <returns>The value of the key in the dictionary after updating.</returns> public static TValue AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value) { dictionary[key] = value; return value; } /// <summary> /// Converts a name/value collection to a dictionary. /// </summary> /// <param name="collection">Name/value collection.</param> /// <returns>Dictionary converted from a name/value collection.</returns> public static Dictionary<string, string> ToDictionary(this NameValueCollection collection) { return collection.AllKeys.ToDictionary(key => key, key => collection[key]); } /// <summary> /// Returns <c>true</c> if any item in <see cref="BitArray"/> is equal to <paramref name="value"/>. /// </summary> /// <param name="source">Source <see cref="BitArray"/>.</param> /// <param name="value"><see cref="bool"/> value to test for.</param> /// <returns><c>true</c> if any item in <see cref="BitArray"/> is equal to <paramref name="value"/>.</returns> public static bool Any(this BitArray source, bool value) { return source.Cast<bool>().Any(item => item == value); } /// <summary> /// Returns <c>true</c> if all items in <see cref="BitArray"/> are equal to <paramref name="value"/>. /// </summary> /// <param name="source">Source <see cref="BitArray"/>.</param> /// <param name="value"><see cref="bool"/> value to test for.</param> /// <returns><c>true</c> if all items in <see cref="BitArray"/> are equal to <paramref name="value"/>.</returns> public static bool All(this BitArray source, bool value) { return source.Cast<bool>().All(item => item == value); } /// <summary> /// Returns the majority value in the collection, or default type value if no item represents the majority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the majority element.</param> /// <returns>The majority value in the collection.</returns> public static T Majority<T>(this IEnumerable<T> source) { return source.Majority(default(T)); } /// <summary> /// Returns the majority value in the collection, or <paramref name="defaultValue"/> if no item represents the majority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the majority element.</param> /// <param name="defaultValue">Default value to return if no item represents the majority.</param> /// <returns>The majority value in the collection.</returns> public static T Majority<T>(this IEnumerable<T> source, T defaultValue) { T majority = defaultValue; if ((object)source == null) return majority; if (source.Count() > 1) { Dictionary<T, int> itemCounts = new Dictionary<T, int>(); int count; // Count each number of items in the list foreach (T item in source) { if (itemCounts.TryGetValue(item, out count)) { count++; itemCounts[item] = count; } else { itemCounts.Add(item, 1); } } // Find the largest number of items in the list KeyValuePair<T, int> maxItem = itemCounts.Max((a, b) => (a.Value < b.Value ? -1 : (a.Value > b.Value ? 1 : 0))); // If item with largest count has a plural majority, then it is the majority item if (maxItem.Value > 1) majority = maxItem.Key; } else { majority = source.FirstOrDefault(); } return majority; } /// <summary> /// Returns the minority value in the collection, or default type value if no item represents the minority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the minority element.</param> /// <returns>The minority value in the collection.</returns> public static T Minority<T>(this IEnumerable<T> source) { return source.Minority(default(T)); } /// <summary> /// Returns the minority value in the collection, or <paramref name="defaultValue"/> if no item represents the minority. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="source"/>.</typeparam> /// <param name="source">An enumeration over which to find the minority element.</param> /// <param name="defaultValue">Default value to return if no item represents the minority.</param> /// <returns>The minority value in the collection.</returns> public static T Minority<T>(this IEnumerable<T> source, T defaultValue) { T minority = defaultValue; if ((object)source == null) return minority; if (source.Count() > 1) { Dictionary<T, int> itemCounts = new Dictionary<T, int>(); int count; // Count each number of items in the list foreach (T item in source) { if (itemCounts.TryGetValue(item, out count)) { count++; itemCounts[item] = count; } else { itemCounts.Add(item, 1); } } // Find the smallest number of items in the list KeyValuePair<T, int> minItem = itemCounts.Min((a, b) => (a.Value < b.Value ? -1 : (a.Value > b.Value ? 1 : 0))); minority = minItem.Key; } else { minority = source.FirstOrDefault(); } return minority; } /// <summary> /// Adds the specified <paramref name="items"/> to the <paramref name="collection"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection to which the <paramref name="items"/> are to be added.</param> /// <param name="items">The elements to be added to the <paramref name="collection"/>.</param> public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items) { foreach (T item in items) { collection.Add(item); } } /// <summary> /// Updates <paramref name="collection"/> starting at the <paramref name="index"/> with the specified <paramref name="items"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection whose elements are to be updated with the specified <paramref name="items"/>.</param> /// <param name="index">The zero-based index in the <paramref name="collection"/> at which elements are to be updated.</param> /// <param name="items">The elements that will replace the <paramref name="collection"/> elements starting at the <paramref name="index"/>.</param> /// <exception cref="ArgumentOutOfRangeException">The specified <paramref name="index"/> is present in the <paramref name="collection"/>.</exception> public static void UpdateRange<T>(this IList<T> collection, int index, IEnumerable<T> items) { foreach (T item in items) { collection[index++] = item; } } /// <summary> /// Returns elements in the specified range from the <paramref name="collection"/>. /// </summary> /// <typeparam name="T"><see cref="Type"/> of elements in the <paramref name="collection"/>.</typeparam> /// <param name="collection">The collection from which elements are to be retrieved.</param> /// <param name="index">The 0-based index position in the <paramref name="collection"/> from which elements are to be retrieved.</param> /// <param name="count">The number of elements to be retrieved from the <paramref name="collection"/> starting at the <paramref name="index"/>.</param> /// <returns>An <see cref="IList{T}"/> object.</returns> public static IList<T> GetRange<T>(this IList<T> collection, int index, int count) { List<T> result = new List<T>(); for (int i = index; i < index + count; i++) { result.Add(collection[i]); } return result; } /// <summary> /// Returns the index of the first element of the sequence that satisfies a condition or <c>-1</c> if no such element is found. /// </summary> /// <param name="source">A <see cref="IList{T}"/> to find an index in.</param> /// <param name="predicate">A function to test each element for a condition.</param> /// <returns>Index of the first element in <paramref name="source"/> that matches the specified <paramref name="predicate"/>; otherwise, <c>-1</c>.</returns> /// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam> public static int IndexOf<T>(this IList<T> source, Func<T, bool> predicate)