Вызывая кретинов кода - альтернативы вложенным циклам?

Для меня (или, вероятно, для кого-то еще) не редкость иметь список объектов, которые мне нужно перебрать, а затем взаимодействовать со списком свойств. Я использую вложенный цикл, например так:

IList<T> listOfObjects;
IList<TProperty> listOfProperties;

foreach (T dataObject in listOfObjects)
{
    foreach (TProperty property in listOfProperties)
    {
        //do something clever and extremely useful here
    }
}

Это время и производительность проверена модель для этой проблемы? Или есть что-то более производительное, более элегантное или просто забавное (хотя, конечно, читаемое и поддерживаемое)?

Код выше не заставляет меня улыбаться. Может кто-нибудь помочь принести радость моей петле?

Спасибо!

Обновление: я использую термин "ботаник" в наиболее позитивном смысле. Как часть определения в Википедии, это означает, что «это относится к человеку, который страстно занимается интеллектуальной деятельностью». Под «ботаником кода» я подразумеваю того, кто обеспокоен постоянным совершенствованием себя как программиста, поиском новых, новых и элегантных способов кодирования, которые бывают быстрыми, легко обслуживаемыми и красивыми! Они радуются выходу из VB6 и хотят, чтобы умные люди критиковали свой код и помогали им самим себя почувствовать. (Примечание: им также нравится создавать новые слова, заканчивающиеся на -ify).

Конечная нота:

Спасибо Dave R, Earwicker и TheSoftwareJedi за то, что отправили меня по пути Linq. Это просто тот счастливый код, который я искал!

13.12.2008 15:50:10
Почему этот вопрос начинается с "вызывающих кодов"? Мне не нравится термин "ботаник". Это сайт для программистов. Являются ли «ботаники кода» подмножеством «программистов»? У меня такое ощущение, что мистер Джипстер не включает себя в эту категорию, думает ли он себя лучше, чем «ботаники кода»?
Guge 13.12.2008 17:22:35
Так много людей здесь предпочитают говорить о процессе вместо кода. Непрерывный "почему ты это делаешь?" немного устает в конце концов. Мне нравится;)
krosenvold 13.12.2008 17:33:24
Для Java-программистов homepages.mcs.vuw.ac.nz/~djp/jql является отправной точкой. Предполагая, что ваши вложенные циклы предназначены для обнаружения условий и совпадений равенства; выше бы сделал свое дело. Но нет, если нужны сложные бизнес-правила. Не знаю эквивалента в C #, извините, приятель
questzen 13.12.2008 17:40:24
Пожалуйста, смотрите обновленное название и описание, чтобы ответить на вопросы Гуге.
Steve 13.12.2008 17:54:22
8 ОТВЕТОВ
РЕШЕНИЕ

Похоже, вы пытаетесь декартово объединить два списка и применить условие where. Вот простой пример, показывающий синтаксис Linq для этого, и я думаю, это то, что вы ищете. list1 и list2 могут быть любым IEnumerable, ваше предложение where может содержать более подробную логику, а в предложении select вы можете найти то, что вам нужно.

        var list1 = Enumerable.Range(1, 100);
        var list2 = Enumerable.Range(1, 100);

        foreach (var item in from a in list1
                             from b in list2
                             where a % b == 0
                             select new { a, b })
        {
            Console.WriteLine(item);
        };

Производительность будет идентична той, что вы опубликовали, хотя - нет никакого желания вводить в заблуждение на этот счет. Я предпочитаю этот синтаксис Linq.

8
13.12.2008 17:15:35

В таком сценарии мы часто начинаем с фильтрации интересующих нас фрагментов. Ваш блок dosomethingclever () обычно начинается в

foreach (T dataObject in listOfObjects)
{    
  foreach (TProperty property in listOfProperties)    
  {
    if (property.something == "blah") 
    { // OK, we found the piece we're interested in...

      // do something clever...

    }
  }
}

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

Тонны образцов здесь .

0
13.12.2008 16:01:48

Если вам нужно что-то сделать с каждым объектом и каждым свойством, делать не так много. Возможно, вы сможете делать некоторые синтаксически приятные вещи, но нет способа обойти эту работу.

Если вы работаете только с подмножеством объектов и / или свойств, отфильтруйте его (с linq для объектов, если вы делаете .net 3.5)!

Возможно, вам понравится Filter / Map / Reduce для ваших наборов как средство введения лучшего синтаксиса для выполнения операций над множествами.

3
13.12.2008 16:04:16
Я думаю, что он работает над некоторым объединенным декартовым результатом списков, поэтому то, что он делал, не должно подвергаться критике. Он просто ищет более элегантный способ написания. Вложенные петли сосут.
TheSoftwareJedi 13.12.2008 17:11:17
@TheSoftwareJedi - Почему вложенные циклы сосут? Я хотел бы услышать ваши рассуждения.
kirk.burleson 21.07.2010 18:24:17

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

Поскольку вы хотите выполнять действия при переборе коллекции, вы можете обнаружить, что LINQ будет интересным способом изучения:

http://msdn.microsoft.com/en-us/vcsharp/aa904594.aspx

Вы будете ограничивать себя более поздними версиями Framework (начиная с 3.5), но на самом деле подход функционального программирования может показаться вам довольно элегантным. Другие языковые функции, которые вступают в игру, когда вы идете по этому пути, включают лямбды и анонимные методы, которые сами по себе очаровательны.

Желаем удачи, и я надеюсь, что вы повеселитесь в пути - это отличный подход :)

8
13.12.2008 16:15:26
Прекрасный ответ. Конечно, те, кто думает, что вложенные циклы нечитаемы, например, TheSoftwareJedi, могут найти их трудными для чтения. Хотя я не понимаю почему.
kirk.burleson 21.07.2010 18:26:17
foreach (var pair in from obj in listOfObjects
                     from prop in listOfProperties  
                     select new {obj, prop})
{
   Console.WriteLine(pair.obj + ", " + pair.prop);
}
5
13.12.2008 16:59:48
Action<T, TProp> somethingClever = //your clever method

listOfObjects
  .SelectMany(
    o => listOfProperties,
    (o, p) => new {o, p})
  .ToList()
  .ForEach(x => somethingClever(x.o, x.p));
2
15.12.2008 17:27:54
Это выглядит еще более всезнайкой! Ой варианты для счастливого кода! Теперь убедить руководство команды разрешить переход на 3.5 :(
Steve 15.12.2008 18:20:18

Мне нравятся каналы и фильтры Ayende , но это гораздо больше кода, чем встроенный LINQ для простых циклов (я предполагаю, что пример кода в вопросе был тривиальным).

0
15.12.2008 17:35:24

Хотя мне нравится элегантность решений Linq, я думаю, что я бы рекомендовал извлечь внутренний цикл в метод; Ваш код будет выглядеть примерно так:

foreach(dataObject in listOfObjects)
    DoSomethingCleverWithProperties(dataObject, listOfProperties);

Это просто кажется мне более понятным.

2
15.12.2008 17:39:38