按自定义条件分组
Group by custom condition
鉴于:
var arr = new int[] {
10, 20, 30,
10, 20, 30, 40, 50,
10, 20
};
求职:
var group1 = new int [] { 10, 20, 30 };
var group2 = new int [] { 10, 20, 30, 40, 50 };
var group3 = new int [] { 10, 20 };
需要按值分组=>当下一个元素的值低于前一个元素时,创建新组。将不胜感激基于 LINQ 的解决方案。
从技术上讲,你可以这样写:
int prior = int.MinValue;
int group = 0;
var result = arr
.GroupBy(item => {
if (item < prior)
group += 1;
prior = item;
return group;
});
但如果你不坚持IGrouping<int, int>
并同意IEnumerable<int[]>
,foreach
看起来更好(让我们概括解决方案) :
public static partial class EnumerableExtensions {
public static IEnumerable<T[]> GroupByAsc<T>(this IEnumerable<T> source,
Comparer<T> comparer = null) {
if (source is null)
throw new ArgumentNullException(nameof(source));
if ((comparer ??= Comparer<T>.Default) is null)
throw new ArgumentNullException(nameof(comparer),
$"Type {typeof(T).Name} doesn't have default comparer");
List<T> list = new List<T>();
foreach (var item in source)
if (list.Count > 0 && comparer.Compare(list[list.Count - 1], item) <= 0)
list.Add(item);
else {
if (list.Count > 0)
yield return list.ToArray();
list.Clear();
list.Add(item);
}
if (list.Count > 0)
yield return list.ToArray();
}
}
用法:
var result = arr
.GroupByAsc();
试试这个
void Main()
{
var arrList= arr.GroupCollection<int>().ToArray();
if (arrList.Count() < 3) Console.WriteLine("Error! Array is too short");
arrList.Dump();
var group1=arrList[0].ToArray();
var group2=arrList[1].ToArray();
var group3=arrList[2].ToArray();
}
扩展
public static class Util
{
public static IEnumerable<IEnumerable<T>> GroupCollection<T>(this IEnumerable<T> arr) where T:IComparable
{
var arrList = new List<List<T>>();
var prevItem = arr.First();
var currList = new List<T>();
foreach (var item in arr)
{
if (item.CompareTo(prevItem) < 0)
{
arrList.Add(currList);
currList = new List<T>();
}
currList.Add(item);
prevItem = item;
}
arrList.Add(currList);
return arrList;
}
}
鉴于:
var arr = new int[] {
10, 20, 30,
10, 20, 30, 40, 50,
10, 20
};
求职:
var group1 = new int [] { 10, 20, 30 };
var group2 = new int [] { 10, 20, 30, 40, 50 };
var group3 = new int [] { 10, 20 };
需要按值分组=>当下一个元素的值低于前一个元素时,创建新组。将不胜感激基于 LINQ 的解决方案。
从技术上讲,你可以这样写:
int prior = int.MinValue;
int group = 0;
var result = arr
.GroupBy(item => {
if (item < prior)
group += 1;
prior = item;
return group;
});
但如果你不坚持IGrouping<int, int>
并同意IEnumerable<int[]>
,foreach
看起来更好(让我们概括解决方案) :
public static partial class EnumerableExtensions {
public static IEnumerable<T[]> GroupByAsc<T>(this IEnumerable<T> source,
Comparer<T> comparer = null) {
if (source is null)
throw new ArgumentNullException(nameof(source));
if ((comparer ??= Comparer<T>.Default) is null)
throw new ArgumentNullException(nameof(comparer),
$"Type {typeof(T).Name} doesn't have default comparer");
List<T> list = new List<T>();
foreach (var item in source)
if (list.Count > 0 && comparer.Compare(list[list.Count - 1], item) <= 0)
list.Add(item);
else {
if (list.Count > 0)
yield return list.ToArray();
list.Clear();
list.Add(item);
}
if (list.Count > 0)
yield return list.ToArray();
}
}
用法:
var result = arr
.GroupByAsc();
试试这个
void Main()
{
var arrList= arr.GroupCollection<int>().ToArray();
if (arrList.Count() < 3) Console.WriteLine("Error! Array is too short");
arrList.Dump();
var group1=arrList[0].ToArray();
var group2=arrList[1].ToArray();
var group3=arrList[2].ToArray();
}
扩展
public static class Util
{
public static IEnumerable<IEnumerable<T>> GroupCollection<T>(this IEnumerable<T> arr) where T:IComparable
{
var arrList = new List<List<T>>();
var prevItem = arr.First();
var currList = new List<T>();
foreach (var item in arr)
{
if (item.CompareTo(prevItem) < 0)
{
arrList.Add(currList);
currList = new List<T>();
}
currList.Add(item);
prevItem = item;
}
arrList.Add(currList);
return arrList;
}
}