using System;
using System.Collections.Generic;
using System.Linq;
namespace Semmle.Util
{
public static class IEnumerableExtensions
{
///
/// Find the first element in the sequence, or null if the sequence is empty.
///
/// The type of the sequence.
/// The list of items.
/// The first item, or null if the sequence is empty.
public static T? FirstOrNull(this IEnumerable list) where T : struct
{
return list.Any() ? (T?)list.First() : null;
}
///
/// Finds the last element a sequence, or null if the sequence is empty.
///
/// The type of the elements in the sequence.
/// The list of items.
/// The last item, or null if the sequence is empty.
public static T? LastOrNull(this IEnumerable list) where T : struct
{
return list.Any() ? (T?)list.Last() : null;
}
///
/// Interleaves the elements from the two sequences.
///
public static IEnumerable Interleave(this IEnumerable first, IEnumerable second)
{
using var enumerator1 = first.GetEnumerator();
using var enumerator2 = second.GetEnumerator();
bool moveNext1;
while ((moveNext1 = enumerator1.MoveNext()) && enumerator2.MoveNext())
{
yield return enumerator1.Current;
yield return enumerator2.Current;
}
if (moveNext1)
{
// `first` has more elements than `second`
yield return enumerator1.Current;
while (enumerator1.MoveNext())
{
yield return enumerator1.Current;
}
}
while (enumerator2.MoveNext())
{
// `second` has more elements than `first`
yield return enumerator2.Current;
}
}
///
/// Enumerates a possibly null enumerable.
/// If the enumerable is null, the list is empty.
///
public static IEnumerable EnumerateNull(this IEnumerable? items)
{
if (items is null)
yield break;
foreach (var item in items) yield return item;
}
///
/// Applies the action to each item in this collection.
///
public static void ForEach(this IEnumerable items, Action a)
{
foreach (var item in items)
a(item);
}
///
/// Forces enumeration of this collection and discards the result.
///
public static void Enumerate(this IEnumerable items)
{
items.ForEach(_ => { });
}
///
/// Computes a hash of a sequence.
///
/// The type of the item.
/// The list of items to hash.
/// The hash code.
public static int SequenceHash(this IEnumerable items) where T : notnull
{
var h = 0;
foreach (var i in items)
h = h * 7 + i.GetHashCode();
return h;
}
}
}