Обращение к коллегам-программистам — альтернативы вложенным циклам?

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

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. Это именно тот счастливый код, который я искал!


person Steve    schedule 13.12.2008    source источник
comment
Почему этот вопрос начинается с вызова программистов? Мне не нравится термин ботаник. Это сайт для программистов. Являются ли программисты ботаниками подмножеством программистов? У меня такое чувство, что мистер Джипстер не включает себя в эту категорию, считает ли он себя лучше программистов?   -  person Guge    schedule 13.12.2008
comment
Многие здесь предпочитают говорить о процессе, а не о коде. Непрерывное, почему ты это делаешь? под конец немного устает. Мне это нравится ;)   -  person krosenvold    schedule 13.12.2008
comment
Для программистов Java: homepages.mcs.vuw.ac.nz/~djp/jql является отправной точкой. Предполагая, что ваши вложенные циклы предназначены для обнаружения условий и совпадений равенства; выше будет делать свое дело. Но не в том случае, если необходимы сложные бизнес-правила. Не знаю эквивалент C#, извини, приятель   -  person questzen    schedule 13.12.2008
comment
См. обновленное название и описание, чтобы ответить на вопросы Гуге.   -  person Steve    schedule 13.12.2008


Ответы (7)


Похоже, вы пытаетесь декартово объединить два списка и применить предложение 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.

person TheSoftwareJedi    schedule 13.12.2008

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

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

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

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

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

person Dave R.    schedule 13.12.2008
comment
Замечательный ответ. Конечно, тем, кто считает вложенные циклы нечитаемыми, как TheSoftwareJedi, может показаться, что их трудно читать. Хотя я не понимаю, почему. - person kirk.burleson; 21.07.2010

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

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

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

person Joel Meador    schedule 13.12.2008
comment
Я думаю, что он работает над каким-то декартовым соединением результатов списков, так что его действия не должны подвергаться критике. Он просто ищет более элегантный способ написать это. Вложенные циклы отстой. - person TheSoftwareJedi; 13.12.2008
comment
@TheSoftwareJedi - Почему вложенные циклы отстой? Я хотел бы услышать ваши рассуждения. - person kirk.burleson; 21.07.2010

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

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

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

person Chris Shaffer    schedule 15.12.2008

В таком сценарии мы часто начинаем с фильтрации интересующих нас фрагментов. Ваш блок 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. Конечно, вам все равно может понадобиться перебрать набор результатов.

Множество примеров здесь.

person Serge Wautier    schedule 13.12.2008

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

person Anthony Mastrean    schedule 15.12.2008

person    schedule
comment
Это выглядит еще более занудно! О, варианты счастливого кода! Теперь, чтобы убедить тимлида разрешить переход на 3.5 :( - person Steve; 15.12.2008