用于验证列表是升序还是降序的Linq表达式
本文关键字:Linq 表达式 降序 升序 验证 列表 用于 | 更新日期: 2023-09-27 18:02:43
我有一个IEnumerable<DateTime>
变量,我需要验证它是升序排序还是降序排序。
我可以使用for循环做到这一点,但是有一种方法可以使用LINQ表达式做到这一点吗?
升序:
myEnumerable.Zip(myEnumerable.Skip(1), (curr, next) => curr <= next).All(x => x);
下行:
myEnumerable.Zip(myEnumerable.Skip(1), (curr, next) => curr >= next).All(x => x);
但是使用循环,LINQ不是万能的。
var orderedByAsc = input.OrderBy(d => d);
if (input.SequenceEqual(orderedByAsc))
{
Console.WriteLine("Ordered by Asc");
return;
}
var orderedByDsc = input.OrderByDescending(d => d);
if (input.SequenceEqual(orderedByDsc))
{
Console.WriteLine("Ordered by Dsc");
return;
}
Console.WriteLine("not sorted");
LINQ扩展。MoreLinq库的良好候选:
public static bool IsOrdered<T>(this IEnumerable<T> source, IComparer<T> comparer = null)
{
return source.IsOrdered(OrderByDirection.Ascending, comparer);
}
public static bool IsOrdered<T>(this IEnumerable<T> source, OrderByDirection direction, IComparer<T> comparer = null)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (comparer == null)
{
comparer = Comparer<T>.Default;
}
int d = direction == OrderByDirection.Ascending ? 1 : -1;
Func<T, T, int> compareFunc= (i1, i2) => d * comparer.Compare(i1, i2);
return IsOrderedImpl(source, compareFunc);
}
public static bool IsOrdered<T>(this IEnumerable<T> source, Func<T, T, int> compareFunc)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (compareFunc == null)
{
throw new ArgumentNullException(nameof(compareFunc));
}
return IsOrderedImpl(source, compareFunc);
}
private static bool IsOrderedImpl<T>(this IEnumerable<T> source, Func<T, T, int> compareFunc)
{
T prevItem = default(T);
int i = 0;
foreach (T item in source)
{
if (i == 0)
{
prevItem = item;
}
else
{
if (compareFunc(prevItem, item) > 0)
{
return false;
}
prevItem = item;
}
++i;
}
return true;
}
[TestMethod]
public void TestIsOrdered01()
{
Assert.IsTrue(Enumerable.Range(1, 10).IsOrdered());
Assert.IsFalse(Enumerable.Range(1, 10).Reverse().IsOrdered());
Assert.IsTrue(Enumerable.Range(1, 10).IsOrdered(OrderByDirection.Ascending));
Assert.IsFalse(Enumerable.Range(1, 10).IsOrdered(OrderByDirection.Descending));
Assert.IsFalse(Enumerable.Range(1, 10).Reverse().IsOrdered(OrderByDirection.Ascending));
Assert.IsTrue(Enumerable.Range(1, 10).Reverse().IsOrdered(OrderByDirection.Descending));
}
如果你确定列表是有序的,那么你可以简单地比较列表的第一个和最后一个元素,看看它是升序还是降序。
这可能是过度设计,但希望是教育和一些使用尽管如此!
public enum SortedState
{
NoValues,
Undecided,
Ascending,
Descending,
Mixture
};
public class AscOrDescHelper<T> where T : IComparable<T>
{
SortedState state;
T lastValue;
bool uniqueValues;
public AscOrDescHelper()
{
state = SortedState.NoValues;
uniqueValues = true; // tentative assumption
}
public AscOrDescHelper<T> ProcessNextValue(T next)
{
switch (state)
{
case SortedState.NoValues:
state = SortedState.Undecided;
break;
case SortedState.Undecided:
case SortedState.Ascending:
case SortedState.Descending:
int cmp = next.CompareTo(lastValue);
switch (state)
{
case SortedState.Undecided:
if (cmp > 0)
{
state = SortedState.Ascending;
}
else if (cmp < 0)
{
state = SortedState.Descending;
}
else
{
uniqueValues = false;
}
break;
case SortedState.Ascending:
if (cmp < 0)
{
state = SortedState.Mixture;
}
else if (cmp == 0)
{
// Not unique
uniqueValues = false;
}
break;
case SortedState.Descending:
if (cmp > 0)
{
state = SortedState.Mixture;
}
else if (cmp == 0)
{
// Not unique
uniqueValues = false;
}
break;
}
break;
}
lastValue = next;
return this;
}
public SortedState State()
{
return state;
}
public bool? Unique()
{
return state == SortedState.Mixture ? (bool?)null : uniqueValues;
}
public override string ToString()
{
return string.Format(
"{0} ({1})",
State(),
Unique().HasValue ? (Unique().Value ? "unique" : "not unique")
: "unknown uniqueness");
}
};
static void CheckIfSorted<T>(IEnumerable<T> values) where T : IComparable<T>
{
Console.WriteLine(
values.Aggregate(
new AscOrDescHelper<T>(),
(last, next) => last.ProcessNextValue(next)));
}
static void Main()
{
CheckIfSorted(new string[]{ "amy", "kate", "sally" });
CheckIfSorted(new int[]{ 7, 5, 5 });
CheckIfSorted(new int[]{ 2, 3, 1 });
// Gives:
// Ascending (unique)
// Descending (not unique)
// Mixture (unknown uniqueness)
}
我是c#初学者,所以欢迎建设性的建议;)