2010-09-19 1 views
7

У меня есть набор объектов модели, которые имеют общее логическое свойство IsVisible. Все, что мне нужно сделать, это найти, если хотя бы один из наборов имеет это значение, равное TRUE. Другими словами, если у меня есть 10 000 объектов, а второй - true, мне не нужно прокручивать остальные 9998. У меня уже есть ответ.Простая проверка, чтобы узнать, имеет ли хотя бы один объект в наборе значение свойства TRUE

Теперь я знаю, что могу написать собственную функцию итерации и вырваться из первого значения «True», но я надеюсь, что это может сделать LINQ. На самом деле, это даже не обязательно LINQ. Любые предложения приветствуются.

BTW, язык выбора - C#.

Update:

Смотрите мой последний пост здесь. Я добавил несколько тестовых кодов и таймингов. Похоже, что LINQ довольно плохая по производительности по сравнению с тем, что я сам делал тест. Конечно, писать проще, но в критически важных таймингах я не уверен.

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

Я также заметил, что если я не сброшу все на «false», все остальные/повторные тесты кажутся намного быстрее. Как-то, переустановив все на FALSE (который был намеренно переполнен, чтобы проверить именно это ...) меняет ситуацию.

Интересно. Не знаю, куда я пойду. Это не является критически важной системой, поэтому, возможно, я поеду на читаемость, но все же. Интересно.

+1

При оптимизации вы должны отказаться от скорости выполнения с затратами программиста. Большинство разработчиков разработчиков предпочитают покупать больше серверов, чем платить больше программистов, и лишь небольшая часть кода работает на критическом пути. Часто код, который быстрее всего записывает и тестирует выигрыши над кодом, выполняется быстрее всего, когда учитываются все затраты (включая стоимость dev). По моему опыту, Linq намного быстрее записывается, но выполняет медленнее. Он все еще выигрывает почти все время в моем опыте. – Slaggg

+0

Slagg, еще не хватает очков, чтобы проголосовать за комментарии, но знаете, если бы я сделал, вы бы получили один для этого. Может быть очевидным, но красноречивость этого действительно выделяется (не похоже на то, что она делает тоже! Умный мой друг! Очень умно!) – MarqueIV

ответ

16

Метод, который вы ищете, - Enumerable.Any.

bool anyObjectsVisible = myObjects.Any(myObject => myObject.IsVisible); 

Это точная короткозамкнутая семантика, которую вы ищете; пример кода аналогичен:

static bool AreAnyObjectsVisible(IEnumerable<MyObject> myObjects) 
{ 
    foreach (var myObject in myObjects) 
    { 
     if (myObject.IsVisible) return true; 
    } 

    return false; 
} 
+0

Именно это я и ищу! (Я новичок в LINQ. Не могу поверить, что я пропустил это!) Я попытался принять ваш ответ, но он сказал мне, что я должен ждать 12 минут. Я хотя бы проголосовал за это. BTW, хороший БОГ, что было быстро! Не прошло и минуты, как я опубликовал его! Ты жжешь! – MarqueIV

+0

@MarqueIV: Приветствия. Вот отличный ресурс, чтобы узнать LINQ: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx – Ani

+0

Эй, Ари ... в ваш комментарий, я дал мне возможность проверить. НО ... если вы хотите включить что-то многословное, но это не ответ (т. Е. Вы хотите форматирование кода и т. Д.), Является правильным этикетом для редактирования исходного вопроса? (Да, вы правы, что в этом случае это действительно должен был быть отдельный вопрос, но я говорю в целом.) – MarqueIV

3

Если вам нужно на самом деле найти объект, просто использовать .Первый или .FirstOrDefault метод:

var myObject = myCollection.First(x=>x.IsVisible); 

или

var myObject = myCollection.FirstOrDefault(x=>x.IsVisible); 

только разница между ними заключается в том, что метод .First будет генерировать исключение, если в коллекции нет такого объекта, когда второй возвращает значение по умолчанию (null в этом примере).

Если вам просто нужно проверить, есть ли какой-либо объект с этим свойством, используйте

var thereIsVisibleObject = myCollection.Any(x=>x.IsVisible); 

Всего эти методы перестают перебор коллекции, как только соответствующий объект найден.

Или, вы должны проверить, если все объекты являются видимыми/невидимыми, вы можете сделать это:

var allTheObjectsAreVisible = myCollection.All(x=>x.IsVisible); 
var allTheObjectsAreInvisible = myCollection.All(x=>!x.IsVisible); 

Но метод .Все будет перечисление всех элементов (что очевидно из его названия).

+0

Проголосовал за вас, но Ани получил «Принятый ответ», потому что они ответили буквально через 60 секунд после его публикации. (Еще до того, как у меня появилась возможность отредактировать опечатку!) Но это очень большая информация, поэтому я проголосовал за вас. Благодаря!! – MarqueIV

+0

На самом деле, я просто перечитываю ваши комментарии по «Все». Исправьте меня, если я ошибаюсь, но они НЕ будут перечислять все объекты, если ваш предикат возвращает false, поскольку он должен сразу вернуть false немедленно, поэтому ваш комментарий, что они будут перечислять все, что я не уверен, правильно ли это. В конце концов, «все видимы» должны замыкаться так же, как сказать «все ли они невидимы», если хоть один видимый, правильно? (Единственное отличие: один возвращает true, другой - false). Конечно, я основываю это на логике, а не на документации, поэтому не могу сказать точно. – MarqueIV

+0

Я прав. .All() выполняет итерацию через коллекцию, которую вы предоставляете, и возвращает, как только ваш предикат является _false_. –

0

Вот ".Any()" реализация:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    if (predicate == null) 
    { 
     throw Error.ArgumentNull("predicate"); 
    } 
    foreach (TSource local in source) 
    { 
     if (predicate(local)) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

Так вот он, ничего "особенного" с .any(), это не просто оберткой "Еогеасп". Ничего особенного, чтобы протестировать там и ничего не винить в плане микро-микро-микро-оптимизации.

+0

Ваш комментарий по оптимизации «микро-микро-микро» в стороне, все же интересно, что мой код, который выглядит почти идентично тому, что вы опубликовали (без проверки на нуль), в некоторых случаях на 400% быстрее, чем LINQ. Вот что я имел в виду. – MarqueIV

Смежные вопросы