Самый простой способ проверить согласованность нескольких значений в списке объектов

1

Я пытаюсь определить, являются ли несколько значений объектов в коллекции одинаковыми или нет. Я придумал два основных способа сделать это; но ни один из них не является полностью удовлетворительным. В обоих случаях я делаю проверку, сравнивая значения каждого объекта с теми, что указаны в первой коллекции. Во-первых, повторить итерацию коллекции, проверяя каждое значение в одно и то же время:

bool string1Varies = false;
bool string2Varies = false;
bool string3Varies = false;
bool string4Varies = false;


foreach (Foo foo in myFooList)
{
    if (foo.string1 != myFooList[0].string1)
        string1Varies = true;
    if (foo.string2 != myFooList[0].string2)
        string2Varies = true;
    if (foo.string3 != myFooList[0].string3)
        string3Varies = true;
    if (foo.string4 != myFooList[0].string4)
        string4Varies = true;

    //optionally break if all 4 bools are true
}

Если нормальный случай состоит в том, что все значения одинаковы, этот подход имеет то преимущество, что только один раз повторяется сбор, но он несколько подробный. Я мог бы улучшить свою производительность, если бы все 4 варианта были несколько обычными, добавив проверку на разрыв цикла; но это добавит больше накладных расходов на итерацию и сделает ее еще более продолжительной.

В качестве альтернативы я мог вычислять каждый bool индивидуально с помощью Linq:

bool string1Varies = myFooList.All(foo => foo.string1 = myFooList[0].string1);
bool string2Varies = myFooList.All(foo => foo.string2 = myFooList[0].string2);
bool string3Varies = myFooList.All(foo => foo.string3 = myFooList[0].string3);
bool string4Varies = myFooList.All(foo => foo.string4 = myFooList[0].string4);

Преимущество этого заключается в том, что оно кратковременно и быстро заканчивается, если изменение происходит на ранних этапах сбора, но если значения совпадают, это приведет к повторному повторению всей коллекции 4 раза.

Есть ли способ получить лучшее из обоих миров, вычислив все 4 значения в одной легко читаемой операции Linq?

Теги:
linq

3 ответа

1
Лучший ответ

Просто обратите внимание, что нет (практических) оптимизаций, чтобы сделать это быстрее. Для выполнения этой проверки вам понадобятся итерации цикла Θ (n) (с несколькими предположениями).

Ваши условия не имеют зависимости друг от друга, поэтому они должны оставаться независимыми. Изменение многословия, которое вы могли бы сделать, включает переписывание ваших условий в вашем первом решении.

string1Varies |= foo.string1 != myFooList[0].string1;
string2Varies |= foo.string2 != myFooList[0].string2;
string3Varies |= foo.string3 != myFooList[0].string3;
string4Varies |= foo.string4 != myFooList[0].string4;

Я не вижу ничего подобного.

0

Как правильно указал Обувь, если ваши сравнения и несоответствия полностью независимы, насколько я знаю, нет никакого способа сделать это более результативным и сжатым способом, чем утверждение foreach (ваше первое решение). Однако решение Linq можно улучшить, используя Any вместо All:

bool string1Varies = myFooList.Any(foo => foo.string1 != myFooList[0].string1);
bool string2Varies = myFooList.Any(foo => foo.string2 != myFooList[0].string2);
bool string3Varies = myFooList.Any(foo => foo.string3 != myFooList[0].string3);
bool string4Varies = myFooList.Any(foo => foo.string4 != myFooList[0].string4);

Таким образом, если одно из значений отличается, вы не завершаете повторение всей коллекции. Но обратите внимание, что он все еще хуже, чем решение foreach, из-за нескольких итераций.

-2

Для сравнения любой разницы в свойствах объекта:

IEnumerable<long> hashed = myList.Select(
    (item) => new string[] { item.String1, item.String2, item.String3, item.String4 }
    .Aggregate<string, long>(0, (runningHash, actual) => 
        (runningHash + actual.GetHashCode()) * 2654435761 % (int)Math.Pow(2, 32)));

bool areAllSame = hashed.Skip(1)
    .FirstOrDefault((item) => item != hashed.First()) == null;

Что он делает: он создает бегущую хеш-функцию (с алгоритмом хэш-алгоритма) по всем свойствам. GetHashCode не должен быть криптографическим, чтобы сделать конфликты невероятными. Столкновения в этой области очень маловероятны, но, конечно, не невозможны. В противном случае вы всегда можете использовать криптографическую хеш-функцию для безопасной работы. Порядок строк также покрывается, так как текущее значение возвращается для каждого значения.

Не жалуйтесь на детали, воспринимайте это как другой подход. → Один хеш по всем свойствам, которые делают равенство прямо сопоставимым в одном цикле.

Это O (n * m) в худшем случае... (m = количество свойств)

  • 0
    Не сработает Мне нужны значения для каждого отдельного члена / свойства, которое я тестирую. Также я считаю, что Distinct будет повторять всю коллекцию в каждом случае.
  • 0
    Я не уверен точно, что должен делать ваш новый код; но это, кажется, генерирует единственное значение для каждого объекта. Мне нужны отдельные одинаковые / разные значения для каждого из значений, которые я смотрю.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню