лямбда-выражение для проверки правильного порядка списка

Я хочу написать лямбда-выражение, чтобы убедиться, что список упорядочен правильно. У меня есть список, в котором у человека есть свойство Name, например:

IList<Person> people = new List<Person>();
people.Add(new Person(){ Name = "Alan"});
people.Add(new Person(){ Name = "Bob"});
people.Add(new Person(){ Name = "Chris"});

Я пытаюсь проверить, что список упорядочен ASC по свойству Name. Итак, мне нужно что-то вроде

Assert.That(people.All(....), "list of person not ordered correctly");

Как я могу написать лямбду, чтобы проверить, что у каждого человека в списке имя меньше, чем у следующего человека в списке?


person Dav Evans    schedule 16.04.2009    source источник
comment
Один быстрый совет: если вы используете конструктор без параметров в инициализаторе объекта, вам не нужен метод (). Например: people.Add(new Person {Name = Alan});   -  person Jon Skeet    schedule 16.04.2009


Ответы (4)


Вот альтернатива решению Джареда — это почти то же самое, но с использованием цикла foreach и логической переменной для проверки того, является ли это первой итерацией. Обычно я нахожу это проще, чем повторять вручную:

public static bool IsOrdered<T>(this IEnumerable<T> source)
{
  var comparer = Comparer<T>.Default;
  T previous = default(T);
  bool first = true;

  foreach (T element in source)
  {
      if (!first && comparer.Compare(previous, element) > 0)
      {
          return false;
      }
      first = false;
      previous = element;
  }
  return true;
}
person Jon Skeet    schedule 16.04.2009

Я не верю, что есть какой-либо оператор LINQ, который в настоящее время охватывает этот случай. Однако вы можете написать метод IsOrdered, который выполняет эту работу. Например.

public static bool IsOrdered<T>(this IEnumerable<T> enumerable) {
  var comparer = Comparer<T>.Default;
  using ( var e = enumerable.GetEnumerator() ) {
    if ( !e.MoveNext() ) {
      return true;
    }
    var previous = e.Current;
    while (e.MoveNext()) {
      if ( comparer.Compare(previous, e.Current) > 0) {
        return false;
      }
      previous = e.Current;
    }
    return true;
  }
}

Затем вы можете использовать следующее, чтобы проверить свой список:

var isOrdered = people.Select(x => x.Name).IsOrdered();
person JaredPar    schedule 16.04.2009

Я знаю, что это старый вопрос, но у меня есть очень хорошее решение для этого с использованием Linq:

people.Zip(people.OrderBy(p => p.Name), (a, b) => a == b).All(eq => eq);

По сути, вы объединяете последовательность с упорядоченной последовательностью и проецируете логическое значение, указывающее, равны ли обе записи:

"Alan"  -- "Alan"  => true
"Bob"   -- "Bob"   => true
"Chris" -- "Chris" => true

Затем с помощью метода All вы спрашиваете, все ли элементы в коллекции являются true.

person alf    schedule 13.10.2011

Что о:

people.SequenceEqual( people.OrderBy( x=>x.Name ) );

SequenceEqual() доступен с версии 3.5. Вы можете добавить Distinct() после OrderBy(), если хотите подтвердить отсутствие дубликатов.

person Cameron    schedule 31.05.2013