我正在尝试找到以下代码的LINQ等价物:
NameValueCollection nvc = new NameValueCollection();
List<BusinessLogic.Donation> donations = new List<BusinessLogic.Donation>();
donations.Add(new BusinessLogic.Donation(0, "", "", "");
donations.Add(new BusinessLogic.Donation(0, "", "", "");
donations.Add(new BusinessLogic.Donation(0, "", "", "");
for(var i = 0; i < donations.Count(); i++)
{
// NOTE: item_number_ + i - I need to be able to do this
nvc.Add("item_number_" + i, donations[i].AccountName);
}
我希望我可以使用类似的东西:
NameValueCollection nvc = new NameValueCollection();
List<BusinessLogic.Donation> donations = new List<BusinessLogic.Donation>();
donations.Add(new BusinessLogic.Donation(0, "", "", "");
donations.Add(new BusinessLogic.Donation(0, "", "", "");
donations.Add(new BusinessLogic.Donation(0, "", "", "");
donations.ForEach(x => nvc.Add("item_name_" + ??, x.AccountName);
但我还没有找到一种方法来确定循环所在的迭代。任何帮助将不胜感激!
答案 0 :(得分:21)
LINQ没有ForEach
方法,并且有充分的理由。 LINQ用于执行查询。它旨在从某些数据源获取信息。 不旨在改变数据源。 LINQ查询不应该导致副作用,这正是你在这里做的。
List
类 具有ForEach
方法,这就是您正在使用的方法。因为它实际上不在System.Linq
命名空间中,所以它在技术上不是LINQ的一部分。
问题中的for
循环没有任何问题。尝试以你想要的方式改变它是错误的(从良好的实践角度来看)。
Here是一个更详细讨论此事的链接。
现在,如果您想忽略该建议并使用ForEach
方法,那么编写一个为该操作提供索引的方法并不难:
public static void ForEach<T>(this IEnumerable<T> sequence, Action<int, T> action)
{
// argument null checking omitted
int i = 0;
foreach (T item in sequence)
{
action(i, item);
i++;
}
}
答案 1 :(得分:10)
这有点令人费解,并创建了一个中间集合,但是如何:
donations.Select((x, i) => new {Name = "item_name_" + i, x.AccountName})
.ToList()
.ForEach(x=> nvc.Add(x.Name, x.AccountName));
这使用the overload of Enumerable.Select
which incorporates the index。
我不得不说这样做没有什么可以获得的。您使用中间集合创建了更多的开销,并且IMHO在原始for循环中失去了可读性。
如果您愿意使用foreach
循环代替List.ForEach
,也可以跳过中间集合。请参阅@wageoghe's answer(强烈推荐)。
答案 2 :(得分:6)
如果你真的想使用List.ForEach,那很简单:
//[...]
int i=0;
donations.ForEach(x => nvc.Add("item_name_" + i++, x.AccountName);
答案 3 :(得分:3)
您是否有任何理由不使用Dictionary<string, string>
,因为您的姓名/密钥似乎是唯一的?这会更快,您可以使用ToDictionary
标准查询运算符。
另外,如果您确实希望使用扩展方法(尽管Servy说for循环是正确的解决方案),那么您可以编写自己的方法 - 请参阅here。
答案 4 :(得分:2)
回答@lc的回答。
foreach (var x in donations.Select((d, i) => new {ItemName = "item_name_" + i, AccountName = d.AccountName}))
{
nvc.Add(x.ItemName, x.AccountName);
}
答案 5 :(得分:1)
这是一篇旧文章,但在Google的排名很高,因此我认为更通用的方法是合适的。 (而且,我往往会忘记这是如何完成的,这意味着我每次都必须在Google上搜索...)
假设一个整数列表:
var values = new List<int>() { 2, 3, 4, 0x100, 74, 0xFFFF, 0x0F0F };
要遍历列表并具有索引,请执行以下操作:
values.Select((x, i) => new
{
item = x,
index = i
})
.ToList()
.ForEach(obj =>
{
int value = obj.item;
int valueIndex = obj.index;
});
答案 6 :(得分:1)
这也可以使用聚合来完成。检查以下示例:
var data = new[]
{
"A",
"B",
"C",
"D"
};
var count = data.Aggregate(0, (index, item) =>
{
Console.WriteLine("[{0}] => '{1}'", index, item);
return index + 1;
});
Console.WriteLine("Total items: {0}", count);
Aggregate
在这里用作for
语句。唯一的缺点是,您需要在每次迭代中将索引的值增加1并返回。
答案 7 :(得分:0)
我喜欢通过以下方式做到这一点:
NameValueCollection nvc = new NameValueCollection();
List<BusinessLogic.Donation> donations = new List<BusinessLogic.Donation>();
donations.Add(new BusinessLogic.Donation(0, "", "", ""));
donations.Add(new BusinessLogic.Donation(0, "", "", ""));
donations.Add(new BusinessLogic.Donation(0, "", "", ""));
Enumerable
.Range(0, donations.Count())
.ToList()
.ForEach(i => nvc.Add("item_number_" + i, donations[i].AccountName));
答案 8 :(得分:-1)
试试这个 -
donations.ForEach(x =>
{
int index = donations.IndexOf(x);
nvc.Add("item_name_" + index, x.AccountName);
});