p.c*_*ell 13 c# linq algorithm linq-to-objects
考虑在5或6级深度的对象的一个或多个属性上更改数据成员的要求.
有些子集需要迭代才能到达需要检查和修改的属性.
在这里,我们将调用一种方法来清除Employee的街道地址.由于我们在循环中更改数据,因此当前实现需要一个for
循环来防止异常:
无法分配给"someVariable",因为它是'foreach迭代变量'
这是使用嵌套foreach
和a 的当前算法(混淆)for
.
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题: 可以使用LINQ重新实现此算法吗?要求原始集合通过静态方法调用更改其数据.
更新:我正在思考/倾向于jQuery/selector类型解决方案的方向.我没有以这种方式具体说出这个问题.我意识到我对这个想法的影响太大(没有副作用).谢谢大家!如果有这样的方法来执行类似jQuery的选择器,请让我们看看它!
Meh*_*ari 19
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);
Run Code Online (Sandbox Code Playgroud)
Sta*_* R. 13
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);
Run Code Online (Sandbox Code Playgroud)
Jos*_*h E 12
LINQ不用于修改对象集.您不希望SELECT sql语句修改所选行的值,不是吗?它有助于记住LINQ代表什么 - 语言集成自然查询.修改linq查询中的对象是恕我直言,反模式.
我认为Stan R.的回答是使用foreach循环的更好的解决方案.
Jay*_*uzi 10
我不喜欢在同一语句中混合使用"查询理解"语法和点名方法调用语法.
我喜欢将查询与动作分开的想法.这些在语义上是不同的,因此在代码中将它们分开通常是有意义的.
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);
}
Run Code Online (Sandbox Code Playgroud)
关于代码的一些风格说明; 这些是个人的,所以我可能不同意:
Emps
,emp
,addr
)addr
对比Addresses
):选择一个并坚持下去type
字段设为字符串是代码气味.如果你可以做到这一点,enum
你的代码可能会更好.