This function divides a sequence into partitions, where a partition is a list of consecutive matching elements.
Example
Input: (A, A, B, B, B, A, C, C)
Output: ((A, A), (B, B, B), (A), (C, C))
I've tried to make this code "obviously correct", but it still doesn't look that way to me.
public static IEnumerable<List<T>> PartitionBy<T, PK>(this IEnumerable<T> sequence, Func<T, PK> partitionKey)
{
return sequence.PartitionBy(partitionKey, EqualityComparer<PK>.Default);
}
public static IEnumerable<List<T>> PartitionBy<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
{
return sequence.PartitionBy(item => item, comparer);
}
public static IEnumerable<List<T>> PartitionBy<T, X>(this IEnumerable<T> sequence, Func<T, X> partitionKey, IEqualityComparer<X> comparer)
{
var itr = sequence.GetEnumerator();
if (!itr.MoveNext())
{
// empty sequence was passed in, so return empty sequence
yield break;
}
// Start the first partition.
var currentList = new List<T>(new[] { itr.Current });
while (itr.MoveNext())
{
var key1 = partitionKey(currentList[0]);
var key2 = partitionKey(itr.Current);
if (comparer.Equals(key1, key2))
{
// continue current partition
currentList.Add(itr.Current);
}
else
{
// yield current partition and start a new one
yield return currentList;
currentList = new List<T>(new[] { itr.Current });
}
}
// We know it has at least 1 element here.
yield return currentList;
}
This function divides a sequence into partitions, where a partition is a list of consecutive matching elements.
Example
Input: (A, A, B, B, B, A, C, C)
Output: ((A, A), (B, B, B), (A), (C, C))
I've tried to make this code "obviously correct", but it still doesn't look that way to me.
public static IEnumerable<List<T>> PartitionBy<T, PK>(this IEnumerable<T> sequence, Func<T, PK> partitionKey)
{
return sequence.PartitionBy(partitionKey, EqualityComparer<PK>.Default);
}
public static IEnumerable<List<T>> PartitionBy<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
{
return sequence.PartitionBy(item => item, comparer);
}
public static IEnumerable<List<T>> PartitionBy<T, X>(this IEnumerable<T> sequence, Func<T, X> partitionKey, IEqualityComparer<X> comparer)
{
var itr = sequence.GetEnumerator();
if (!itr.MoveNext())
{
// empty sequence was passed in, so return empty sequence
yield break;
}
// Start the first partition.
var currentList = new List<T>(new[] { itr.Current });
while (itr.MoveNext())
{
var key1 = partitionKey(currentList[0]);
var key2 = partitionKey(itr.Current);
if (comparer.Equals(key1, key2))
{
// continue current partition
currentList.Add(itr.Current);
}
else
{
// yield current partition and start a new one
yield return currentList;
currentList = new List<T>(new[] { itr.Current });
}
}
// We know it has at least 1 element here.
yield return currentList;
}
This function divides a sequence into partitions, where a partition is a list of consecutive matching elements.
Example
Input: (A, A, B, B, B, A, C, C)
Output: ((A, A), (B, B, B), (A), (C, C))
I've tried to make this code "obviously correct", but it still doesn't look that way to me.
public static IEnumerable<List<T>> PartitionBy<T, PK>(this IEnumerable<T> sequence, Func<T, PK> partitionKey)
{
return sequence.PartitionBy(partitionKey, EqualityComparer<PK>.Default);
}
public static IEnumerable<List<T>> PartitionBy<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
{
return sequence.PartitionBy(item => item, comparer);
}
public static IEnumerable<List<T>> PartitionBy<T, X>(this IEnumerable<T> sequence, Func<T, X> partitionKey, IEqualityComparer<X> comparer)
{
var itr = sequence.GetEnumerator();
if (!itr.MoveNext())
{
// empty sequence was passed in, so return empty sequence
yield break;
}
// Start the first partition.
var currentList = new List<T>(new[] { itr.Current });
while (itr.MoveNext())
{
var key1 = partitionKey(currentList[0]);
var key2 = partitionKey(itr.Current);
if (comparer.Equals(key1, key2))
{
// continue current partition
currentList.Add(itr.Current);
}
else
{
// yield current partition and start a new one
yield return currentList;
currentList = new List<T>(new[] { itr.Current });
}
}
// We know it has at least 1 element here.
yield return currentList;
}
Partitioning a sequence into sublists
This function divides a sequence into partitions, where a partition is a list of consecutive matching elements.
Example
Input: (A, A, B, B, B, A, C, C)
Output: ((A, A), (B, B, B), (A), (C, C))
I've tried to make this code "obviously correct", but it still doesn't look that way to me.
public static IEnumerable<List<T>> PartitionBy<T, PK>(this IEnumerable<T> sequence, Func<T, PK> partitionKey)
{
return sequence.PartitionBy(partitionKey, EqualityComparer<PK>.Default);
}
public static IEnumerable<List<T>> PartitionBy<T>(this IEnumerable<T> sequence, IEqualityComparer<T> comparer)
{
return sequence.PartitionBy(item => item, comparer);
}
public static IEnumerable<List<T>> PartitionBy<T, X>(this IEnumerable<T> sequence, Func<T, X> partitionKey, IEqualityComparer<X> comparer)
{
var itr = sequence.GetEnumerator();
if (!itr.MoveNext())
{
// empty sequence was passed in, so return empty sequence
yield break;
}
// Start the first partition.
var currentList = new List<T>(new[] { itr.Current });
while (itr.MoveNext())
{
var key1 = partitionKey(currentList[0]);
var key2 = partitionKey(itr.Current);
if (comparer.Equals(key1, key2))
{
// continue current partition
currentList.Add(itr.Current);
}
else
{
// yield current partition and start a new one
yield return currentList;
currentList = new List<T>(new[] { itr.Current });
}
}
// We know it has at least 1 element here.
yield return currentList;
}