我有一个IEnumerable<DateTime>
var,如果它按升序或降序排序,我需要验证。
我可以使用for循环来做到这一点,但有没有办法使用LINQ表达式?
答案 0 :(得分:8)
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");
答案 1 :(得分:6)
升序:
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不是一切的神奇解决方案。
答案 2 :(得分:2)
如果您确定该列表是有序的,那么您可以简单地比较列表的第一个和最后一个元素,看它是按升序还是降序。
答案 3 :(得分:0)
这可能是过度设计但有希望教育和一些用途!
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#初学者,所以欢迎建设性的建议;)
答案 4 :(得分:0)
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));
}