1036 lines · 50.7 KB · C#
RawDownload
//******************************************************************************************************//  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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t