C# List<T>.ForEach 带索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13054281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:29:44  来源:igfitidea点击:

List<T>.ForEach with index

c#linqgenerics

提问by James Hill

I'm trying to find the LINQ equivalent of the following code:

我正在尝试找到与以下代码等效的 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);
}

I was hoping I could use something like:

我希望我可以使用类似的东西:

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

But I've not found a way to determine which iteration the loop is on. Any help would be appreciated!

但是我还没有找到一种方法来确定循环处于哪个迭代。任何帮助,将不胜感激!

采纳答案by Servy

LINQ doesn't have a ForEachmethod, and for good reason. LINQ is for performing queries. It is designed to get information from some data source. It is notdesigned to mutate data sources. LINQ queries shouldn't cause side effects, which is exactly what you're doing here.

LINQ 没有ForEach方法,这是有充分理由的。LINQ 用于执行查询。它旨在从某些数据源获取信息。它不是为了改变数据源设计的。LINQ 查询不应引起副作用,这正是您在这里所做的。

The Listclass doeshave a ForEachmethod, which is what you are using. Because it's not actually in the System.Linqnamespace it's not technically a part of LINQ.

List确实有一个ForEach方法,这是你使用的是什么。因为它实际上不在System.Linq命名空间中,所以它在技术上不是 LINQ 的一部分。

There is nothing wrong with the forloop in your question. It would be wrong (from a good practice perspective) to try to change it in the way that you're trying to.

for您的问题中的循环没有任何问题。尝试以您想要的方式改变它是错误的(从良好实践的角度来看)。

Hereis a link that discusses the matter in more detail.

是一个更详细讨论此事的链接。

Now, if you want to ignore that advice and use a ForEachmethod anyway, it's not hard to write one that provides an index to the action:

现在,如果您想忽略该建议并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++;
    }
}

回答by lc.

It's a little convoluted and creates an intermediate collection, but how about:

这有点令人费解并创建了一个中间集合,但是如何:

donations.Select((x, i) => new {Name = "item_name_" + i, x.AccountName})
    .ToList()
    .ForEach(x=> nvc.Add(x.Name, x.AccountName));

This uses the overload of Enumerable.Selectwhich incorporates the index.

这使用Enumerable.Select包含索引的重载

I do have to argue there is nothing really to gain from doing it this way. You create more overhead with the intermediate collection and IMHO lose readability over your original for-loop.

我不得不争辩说,这样做并没有什么真正的好处。您使用中间集合创建了更多开销,恕我直言,您的原始 for 循环会失去可读性。

You can also skip the intermediate collection if you're willing to use foreachloop instead of List.ForEach. See @wageoghe's answer(again highly recommended).

如果您愿意使用foreach循环而不是List.ForEach. 请参阅@wageoghe 的回答(再次强烈推荐)。

回答by Rohit Vats

Try this -

尝试这个 -

donations.ForEach(x =>
         {
             int index = donations.IndexOf(x);
             nvc.Add("item_name_" + index, x.AccountName);
         });

回答by devdigital

Is there any reason you're not using a Dictionary<string, string>as your names/keys appear to be unique? This would be faster and you could use the ToDictionarystandard query operator.

您是否有任何理由不使用 aDictionary<string, string>因为您的姓名/键似乎是唯一的?这会更快,您可以使用ToDictionary标准查询运算符。

Also, if you did wish to use an extension method (although as Servy says a for loop is the right solution here), then you could write your own - see here.

此外,如果您确实希望使用扩展方法(尽管正如 Servy 所说,for 循环是此处的正确解决方案),那么您可以编写自己的方法 - 请参阅此处

回答by wageoghe

Piggybacking on the answer by @lc.

捎带@lc的答案。

foreach (var x in donations.Select((d, i) => new {ItemName = "item_name_" + i, AccountName = d.AccountName}))
{
  nvc.Add(x.ItemName, x.AccountName);
}

回答by Tiago Raposo

If you really want to use a List.ForEach, it's simple:

如果你真的想使用 List.ForEach,这很简单:

//[...]
int i=0;
donations.ForEach(x => nvc.Add("item_name_" + i++, x.AccountName);

回答by an.dr.eas.k

I like to do that the following way:

我喜欢这样做:

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

回答by Patrick Ribbing

This is an old post but is highly ranked by Google so I figured a more generic approach would be suitable. (Also, I tend to forget how this is done which means I have to google every time...)

这是一篇旧帖子,但谷歌排名很高,所以我认为更通用的方法是合适的。(另外,我往往忘记这是如何完成的,这意味着我每次都必须谷歌......)

Assume a list of integers:

假设一个整数列表:

var values = new List<int>() { 2, 3, 4, 0x100, 74, 0xFFFF, 0x0F0F };

var values = new List<int>() { 2, 3, 4, 0x100, 74, 0xFFFF, 0x0F0F };

To iterate the list and having an index do the following:

要迭代列表并拥有索引,请执行以下操作:

values.Select((x, i) => new
{
    item = x,
    index = i
})
.ToList()
.ForEach(obj =>
{
    int value = obj.item;
    int valueIndex = obj.index;
});

回答by Soroush Falahati

This can be done using aggregate as well. Check the following example:

这也可以使用聚合来完成。检查以下示例:

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

Aggregatehere acts as a forstatement. The only downside is that you need to increase the value of the index by one in each iteration and return it.

Aggregate这里是一个for声明。唯一的缺点是需要在每次迭代中将索引的值加一并返回。