Замена вложенного foreach на LINQ; изменить и обновить свойство глубоко внутри

После множества поисковых запросов и попыток все выше ... Единственное, что решило мою проблему, это команда:

$install_name_tool -id /usr/local/lib/libmysqlclient.18.dylib /usr/local/lib/libmysqlclient.18.dylib

Я использую macbook pro, OSX 10 El Capitan. Дарвин xxxx-MacBook-Pro.local 15.6.0 Ядро Дарвина Версии 15.6.0: Чт 23 июня 18:25:34 PDT 2016; XXX: xnu-3248.60.10 ~ 1 / RELEASE_X86_64 x86_64 Perl: v5.18.2 Mysql: 5.6.19

13
задан p.campbell 26 August 2009 в 20:30
поделиться

7 ответов

LINQ не предназначен для изменения наборов объектов. Вы же не ожидаете, что оператор SELECT sql изменит значения выбранных строк, не так ли? Это помогает вспомнить, что означает LINQ - L anguage IN tegrated Q uery. Модификация объектов в запросе linq - это, IMHO, анти-шаблон.

Ответ Стэна Р. был бы лучшим решением с использованием цикла foreach , я думаю.

12
ответ дан 1 December 2019 в 17:25
поделиться
foreach(var item in company.internalData.Emps
                        .SelectMany(emp => emp.privateData.Addresses)
                        .SelectMany(addr => addr.Items)
                        .Where(addr => addr.Type == "StreetAddress"))
     item.Text = CleanStreetAddressLine(item.Text);
19
ответ дан 1 December 2019 в 17:25
поделиться
var dirtyAddresses = company.internalData.Emps.SelectMany( x => x.privateData.Addresses )
                                              .SelectMany(y => y.Items)
                                              .Where( z => z.Type == "StreetAddress");

  foreach(var addr in dirtyAddresses)
    addr.Text = CleanStreetAddressLine(addr.Text);
13
ответ дан 1 December 2019 в 17:25
поделиться

Грязный однострочник.

company.internalData.Emps.SelectMany(x => x.privateData.Addresses)
    .SelectMany(x => x.Items)
    .Where(x => x.Type == "StreetAddress")
    .Select(x => { x.Text = CleanStreetAddressLine(x.Text); return x; });
2
ответ дан 1 December 2019 в 17:25
поделиться

LINQ не позволяет иметь побочные эффекты. однако вы можете сделать это:

company.internalData.Emps.SelectMany(emp => emp.Addresses).SelectMany(addr => Addr.Items).ToList().ForEach(/*either make an anonymous method or refactor your side effect code out to a method on its own*/);
1
ответ дан 1 December 2019 в 17:25
поделиться

Вы можете это сделать, но на самом деле вы этого не хотите. Несколько блоггеров говорили о функциональной природе Linq, и если вы посмотрите на все методы Linq, поставляемые MS, вы обнаружите, что они не вызывают побочных эффектов. Они производят возвращаемые значения, но больше ничего не меняют. Найдите аргументы в методе Linq ForEach, и вы получите хорошее объяснение этой концепции.

Имея это в виду, то, что вы, вероятно, хотите, будет примерно таким:

var addressItems = company.internalData.Emps.SelectMany(
    emp => emp.privateData.Addresses.SelectMany(
           addr => addr.Items
    )
);
foreach (var item in addressItems)
{
   ...
}

Однако, если вы действительно хотите сделать именно то, что вы спросили, тогда вам нужно двигаться в этом направлении:

var addressItems = company.internalData.Emps.SelectMany(
    emp => emp.privateData.Addresses.SelectMany(
           addr => addr.Items.Select(item =>
           { 
              // Do the stuff
              return item;
           }) 
    )
);
1
ответ дан 1 December 2019 в 17:25
поделиться

Мне не нравится смешивать синтаксис «понимания запроса» и синтаксис вызова метода с точками в то же утверждение.

Мне нравится идея отделить запрос от действия . Они семантически различны, поэтому разделение их в коде часто имеет смысл.

var addrItemQuery = from emp in company.internalData.Emps
                    from addr in emp.privateData.Addresses
                    from addrItem in addr.Items
                    where addrItem.Type == "StreetAddress"
                    select addrItem;

foreach (var addrItem in addrItemQuery)
{
    addrItem.Text = CleanStreetAddressLine(addrItem.Text);
}

Несколько примечаний по стилю вашего кода; они личные, поэтому вы можете не согласиться:

  • В общем, я избегаю сокращений ( Emps , emp , addr )
  • Несогласованные имена более запутаны ( адрес vs. Адреса ): выберите один и придерживайтесь его
  • Слово «число» неоднозначно. Это может быть удостоверение личности («Заключенный номер 378, пожалуйста, сделайте шаг вперед». ) или счет («количество овец на этом поле - 12»). Поскольку мы часто используем обе концепции в коде, важно прояснить это. Я часто использую "index" для первого и "count" для второго.
  • Наличие в поле type строки - это запах кода. Если вы можете сделать его enum , ваш код, вероятно, будет лучше.
10
ответ дан 1 December 2019 в 17:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: