C# 如何检查列表是否已排序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1940214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a list is ordered?
提问by Nicole
I am doing some unit tests and I want to know if there's any way to test if a list is ordered by a property of the objects it contains.
我正在做一些单元测试,我想知道是否有任何方法可以测试列表是否按其包含的对象的属性排序。
Right now I am doing it this way but I don't like it, I want a better way. Can somebody help me please?
现在我正在这样做,但我不喜欢它,我想要一个更好的方式。有人可以帮我吗?
// (fill the list)
List<StudyFeedItem> studyFeeds =
Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);
StudyFeedItem previous = studyFeeds.First();
foreach (StudyFeedItem item in studyFeeds)
{
if (item != previous)
{
Assert.IsTrue(previous.Date > item.Date);
}
previous = item;
}
采纳答案by Mark Seemann
If you are using MSTest, you may want to take a look at CollectionAssert.AreEqual.
如果您使用的是 MSTest,您可能需要查看CollectionAssert.AreEqual。
Enumerable.SequenceEqualmay be another useful API to use in an assertion.
Enumerable.SequenceEqual可能是在断言中使用的另一个有用的 API。
In both cases you should prepare a list that holds the expected list in the expected order, and then compare that list to the result.
在这两种情况下,您都应该准备一个以预期顺序保存预期列表的列表,然后将该列表与结果进行比较。
Here's an example:
下面是一个例子:
var studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);
var expectedList = studyFeeds.OrderByDescending(x => x.Date);
Assert.IsTrue(expectedList.SequenceEqual(studyFeeds));
回答by jason
How about:
怎么样:
var list = items.ToList();
for(int i = 1; i < list.Count; i++) {
Assert.IsTrue(yourComparer.Compare(list[i - 1], list[i]) <= 0);
}
where yourComparer
is an instance of YourComparer
which implements IComparer<YourBusinessObject>
. This ensures that every element is less than the next element in the enumeration.
其中yourComparer
是的一个实例YourComparer
,它实现IComparer<YourBusinessObject>
。这确保每个元素都小于枚举中的下一个元素。
回答by Tanzelax
Something LINQ-y would be to use a separate sorted query...
LINQ-y 将使用单独的排序查询......
var sorted = from item in items
orderby item.Priority
select item;
Assert.IsTrue(items.SequenceEquals(sorted));
Type inference means you'd need a
类型推断意味着你需要一个
where T : IHasPriority
However, if you have multiple items of the same priority, then for a unit test assertion you're probably best off just looping with the list index as Jason suggested.
但是,如果您有多个具有相同优先级的项目,那么对于单元测试断言,您可能最好按照 Jason 的建议使用列表索引进行循环。
回答by Steven M. Cherry
One way or another you're going to have to walk the list and ensure that the items are in the order you want. Since the item comparison is custom, you could look into creating a generic method for this and passing in a comparison function - the same way that sorting the list uses comparison functions.
以一种或另一种方式,您将不得不遍历列表并确保项目按您想要的顺序排列。由于项目比较是自定义的,您可以考虑为此创建一个通用方法并传入一个比较函数 - 与对列表进行排序使用比较函数的方式相同。
回答by Darin Dimitrov
var studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);
var orderedFeeds = studyFeeds.OrderBy(f => f.Date);
for (int i = 0; i < studyFeeds.Count; i++)
{
Assert.AreEqual(orderedFeeds[i].Date, studyFeeds[i].Date);
}
回答by Darin Dimitrov
if(studyFeeds.Length < 2)
return;
for(int i = 1; i < studyFeeds.Length;i++)
Assert.IsTrue(studyFeeds[i-1].Date > studyFeeds[i].Date);
for
isn't dead just quite yet!
for
还没死呢!
回答by J?rn Schou-Rode
If your unit testing framework has helper methods to assert equality of collections, you should be able do something like this (NUnit flavored):
如果你的单元测试框架有辅助方法来断言集合的相等性,你应该能够做这样的事情(NUnit 风格):
var sorted = studyFeeds.OrderBy(s => s.Date);
CollectionAssert.AreEqual(sorted.ToList(), studyFeeds.ToList());
The assert method works with any IEnumerable
, but when both collections are of type IList
or "array of something", the error message thrown when the assert fails will contain the index of the first out-of-place element.
assert 方法适用于 any IEnumerable
,但是当两个集合都是类型IList
或“某物数组”时,断言失败时抛出的错误消息将包含第一个不合适的元素的索引。
回答by Greg Beech
A .NET 4.0 way would be to use the Enumerable.Zip
method to zip the list with itself offset by one, which pairs each item with the subsequent item in the list. You can then check that the condition holds true for each pair, e.g.
.NET 4.0 的一种方法是使用该Enumerable.Zip
方法将列表压缩为自身偏移一,这将每个项目与列表中的后续项目配对。然后,您可以检查每对的条件是否成立,例如
var ordered = studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => new { a, b })
.All(p => p.a.Date < p.b.Date);
If you're on an earlier version of the framework you can write your own Zip method without too much trouble, something like the following (argument validation and disposal of the enumerators if applicable is left to the reader):
如果您使用的是该框架的早期版本,则可以轻松编写自己的 Zip 方法,如下所示(如果适用,则枚举器的参数验证和处理留给读者):
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> selector)
{
var e1 = first.GetEnumerator();
var e2 = second.GetEnumerator();
while (e1.MoveNext() & e2.MoveNext()) // one & is important
yield return selector(e1.Current, e2.Current);
}
回答by jolySoft
Here's how I do it with Linq and I comparable, might not be the best but works for me and it's test framework independent.
这是我使用 Linq 的方法,我可以比较,它可能不是最好的,但对我有用,并且它独立于测试框架。
So the call looks like this:
所以调用看起来像这样:
myList.IsOrderedBy(a => a.StartDate)
This works for anything that implements IComparable, so numbers strings and anything that inherit from IComparable:
这适用于任何实现 IComparable 的东西,所以数字字符串和任何从 IComparable 继承的东西:
public static bool IsOrderedBy<T, TProperty>(this List<T> list, Expression<Func<T, TProperty>> propertyExpression) where TProperty : IComparable<TProperty>
{
var member = (MemberExpression) propertyExpression.Body;
var propertyInfo = (PropertyInfo) member.Member;
IComparable<TProperty> previousValue = null;
for (int i = 0; i < list.Count(); i++)
{
var currentValue = (TProperty)propertyInfo.GetValue(list[i], null);
if (previousValue == null)
{
previousValue = currentValue;
continue;
}
if(previousValue.CompareTo(currentValue) > 0) return false;
previousValue = currentValue;
}
return true;
}
Hope this helps, took me ages to work this one out.
希望这会有所帮助,我花了很长时间才解决这个问题。
回答by mattk
Nunit 2.5 introduced CollectionOrderedContraintand a nice syntax for verifying the order of a collection:
Nunit 2.5 引入了CollectionOrderedContraint和一个很好的语法来验证集合的顺序:
Assert.That(collection, Is.Ordered.By("PropertyName"));
No need to manually order and compare.
无需手动订购和比较。