用LINQ替换嵌套的foreach;修改和更新深度内的属性

考虑对更改的要求,该数据成员是深度为5或6级的对象的一个​​或多个属性。用LINQ替换嵌套的foreach;修改和更新深度内的属性

有些子集需要迭代才能到达需要检查&修改的属性。

这里我们调用一个清除员工街道地址的方法。由于我们在循环中不断变化的数据,目前的实现需要一个for循环,防止异常:

不能分配给“someVariable”,因为它是一个“的foreach迭代变量”

这里的当前算法(混淆)嵌套foreachfor

foreach (var emp in company.internalData.Emps) 

{

foreach (var addr in emp.privateData.Addresses)

{

int numberAddresses = addr.Items.Length;

for (int i = 0; i < numberAddresses; i++)

{

//transform this street address via a static method

if (addr.Items[i].Type =="StreetAddress")

addr.Items[i].Text = CleanStreetAddressLine(addr.Items[i].Text);

}

}

}

问: 可以此算法使用LINQ重新实现?要求是原始集合通过该静态方法调用更改其数据。

更新:我在想/倾向于jQuery /选择器类型的解决方案。我没有那样具体地说这个问题。我意识到我对这个想法过于深刻(没有副作用)。谢谢大家!如果有这种方法来执行类似jQuery的选择器,请让我们看看它!

回答:

LINQ不打算修改对象的集合。您不希望SELECT sql语句修改所选行的值,对吗?它有助于记住LINQ代表什么 - Language Integrated Natural 查询。在linq查询中修改对象,恕我直言,反模式。

Stan R.的回答是使用foreach循环的更好解决方案,我想。

回答:

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);

回答:

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*/); 

回答:

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);

回答:

你可以做到这一点,但你并不是真的想。几位博主谈到了Linq的功能性,如果你看看所有MS提供的Linq方法,你会发现它们不会产生副作用。它们会产生返回值,但它们不会改变其他任何东西。通过Linq ForEach方法搜索参数,您将很好地解释这个概念。

考虑到这一点,你probaly想要的东西是这样的:

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;

})

)

);

回答:

I don't like mixing "query comprehension" syntax and dotted-method-call syntax在相同的声明。

我确实喜欢将查询动作分开。它们在语义上是不同的,因此在代码中分离它们通常是有意义的。

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);

}

有关代码的几个风格说明;这些都是个人的,所以我可能会不同意:

  • 一般情况下,我尽量避免缩写(Empsempaddr
  • 名称不一致是更加令人困惑(addrAddresses):选择一个与坚持它
  • “数字”这个词是含糊不清的。它可以是一个身份(“犯人号码378请前进”)或计数(“该场的羊数为12”)。由于我们在代码中大量使用这两个概念,因此清楚这一点很有价值。我经常使用第一个“索引”和第二个“计数”。
  • 拥有type字段的字符串是一种代码异味。如果你能使它成为一个enum你的代码可能会更好。

回答:

肮脏的单线。

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; });

回答:

要使用foreach循环,我首先创建当地的“列表”变量更新LINQ的结果,然后使用foreach循环执行更新。值以这种方式更新。在这里阅读更多:

How to update value of LINQ results using FOREACH loop

以上是 用LINQ替换嵌套的foreach;修改和更新深度内的属性 的全部内容, 来源链接: utcz.com/qa/257953.html

回到顶部