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

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

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

Почему этот вопрос начинается с "ботаников кода вызова"? Мне не нравится термин «ботаник». Это сайт для программистов. Являются ли "программисты" неким подмножеством "программистов"? У меня такое ощущение, что мистер Джипстер не относит себя к этой категории, считает ли он себя лучше, чем «ботаники-программисты»?

Guge 13.12.2008 20:22

Многие здесь предпочитают говорить о процессе, а не о коде. Непрерывное "зачем ты это делаешь?" в конце концов немного устает. Мне это нравится ;)

krosenvold 13.12.2008 20:33

Для java-программистов homepages.mcs.vuw.ac.nz/~djp/jql является отправной точкой. Предполагая, что ваши вложенные циклы предназначены для обнаружения условий и совпадений на равенство; выше сделает свое дело. Но не тогда, когда нужны сложные бизнес-правила. Не знаю эквивалента C#, извини, дружище

questzen 13.12.2008 20:40

Пожалуйста, просмотрите обновленное название и описание, чтобы ответить на вопросы Guge.

Steve 13.12.2008 20:54
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
4
4 020
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

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

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

Вам может понравиться Фильтр / Карта / Уменьшить для ваших наборов как средство введения лучшего синтаксиса для выполнения операций над наборами.

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

TheSoftwareJedi 13.12.2008 20:11

@TheSoftwareJedi - Почему вложенные циклы - отстой? Хотелось бы услышать ваши рассуждения.

kirk.burleson 21.07.2010 22:24

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

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

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

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

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

Замечательный ответ. Конечно, те, кто считает вложенные циклы нечитаемыми, например TheSoftwareJedi, могут счесть их трудными для чтения. Хотя не понимаю почему.

kirk.burleson 21.07.2010 22:26
foreach (var pair in from obj in listOfObjects
                     from prop in listOfProperties  
                     select new {obj, prop})
{
   Console.WriteLine(pair.obj + ", " + pair.prop);
}
Ответ принят как подходящий

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

Action<T, TProp> somethingClever = //your clever method

listOfObjects
  .SelectMany(
    o => listOfProperties,
    (o, p) => new {o, p})
  .ToList()
  .ForEach(x => somethingClever(x.o, x.p));

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

Steve 15.12.2008 21:20

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

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

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

Мне это кажется более удобным в обслуживании.

Другие вопросы по теме