Extension Methods for C# Array class.
//-----------------------------------------------------------------------
// <copyright file="ArrayExtensions.cs" company="Akka.NET Project">
// Copyright (C) 2009-2019 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2019 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
namespace Akka.Util.Internal
{
/// <summary>
/// Provides extension utilities to arrays.
/// </summary>
internal static class ArrayExtensions
{
/// <summary>
/// Determines if an array is null or empty.
/// </summary>
/// <param name="obj">The array to check.</param>
/// <returns>True if null or empty, false otherwise.</returns>
public static bool IsNullOrEmpty(this Array obj)
{
return ((obj == null) || (obj.Length == 0));
}
/// <summary>
/// Determines if an array is not null or empty.
/// </summary>
/// <param name="obj">The array to check.</param>
/// <returns>True if not null or empty, false otherwise.</returns>
public static bool NonEmpty(this Array obj)
{
return obj != null && obj.Length > 0;
}
/// <summary>
/// Shuffles an array of objects.
/// </summary>
/// <typeparam name="T">The type of the array to sort.</typeparam>
/// <param name="array">The array to sort.</param>
public static void Shuffle<T>(this T[] array)
{
var length = array.Length;
var random = new Random();
while (length > 1)
{
int randomNumber = random.Next(length--);
T obj = array[length];
array[length] = array[randomNumber];
array[randomNumber] = obj;
}
}
/// <summary>
/// Implementation of Scala's ZipWithIndex method.
///
/// Folds a collection into a Dictionary where the original value (of type T) acts as the key
/// and the index of the item in the array acts as the value.
/// </summary>
/// <typeparam name="T">TBD</typeparam>
/// <param name="collection">TBD</param>
/// <returns>TBD</returns>
public static Dictionary<T, int> ZipWithIndex<T>(this IEnumerable<T> collection)
{
var i = 0;
var dict = new Dictionary<T, int>();
foreach (var item in collection)
{
dict.Add(item, i);
i++;
}
return dict;
}
/// <summary>
/// Grabs a subset of an IEnumerable based on a starting index and position
/// </summary>
/// <typeparam name="T">TBD</typeparam>
/// <param name="items">The array of items to slice</param>
/// <param name="startIndex">The starting position to begin the slice</param>
/// <param name="count">The number of items to take</param>
/// <returns>A slice of size <paramref name="count"/> beginning from position <sparamref name="startIndex"/> in <paramref name="items"/>.</returns>
internal static IEnumerable<T> Slice<T>(this IEnumerable<T> items, int startIndex, int count)
{
return items.Skip(startIndex).Take(count);
}
/// <summary>
/// Select all the items in this array beginning with <paramref name="startingItem"/> and up until the end of the array.
///
/// <note>
/// If <paramref name="startingItem"/> is not found in the array, From will return an empty set.
/// If <paramref name="startingItem"/> is found at the end of the array, From will return the entire original array.
/// </note>
/// </summary>
/// <typeparam name="T">TBD</typeparam>
/// <param name="items">TBD</param>
/// <param name="startingItem">TBD</param>
/// <returns>TBD</returns>
internal static IEnumerable<T> From<T>(this IEnumerable<T> items, T startingItem)
{
var itemsAsList = items.ToList();
var indexOf = itemsAsList.IndexOf(startingItem);
if (indexOf == -1) return new List<T>();
if (indexOf == 0) return itemsAsList;
var itemCount = (itemsAsList.Count - indexOf);
return itemsAsList.Slice(indexOf, itemCount);
}
/// <summary>
/// Select all the items in this array from the beginning until (but not including) <paramref name="startingItem"/>
/// <note>
/// If <paramref name="startingItem"/> is not found in the array, Until will select all items.
/// If <paramref name="startingItem"/> is the first item in the array, an empty array will be returned.
/// </note>
/// </summary>
/// <typeparam name="T">TBD</typeparam>
/// <param name="items">TBD</param>
/// <param name="startingItem">TBD</param>
/// <returns>TBD</returns>
internal static IEnumerable<T> Until<T>(this IEnumerable<T> items, T startingItem)
{
var enumerator = items.GetEnumerator();
while (enumerator.MoveNext())
{
var current = enumerator.Current;
if (Equals(current, startingItem))
yield break;
yield return current;
}
}
/// <summary>
/// TBD
/// </summary>
/// <typeparam name="T">TBD</typeparam>
/// <param name="items">TBD</param>
/// <returns>TBD</returns>
internal static IEnumerable<T> Tail<T>(this IEnumerable<T> items)
{
return items.Skip(1);
}
}
}