24

次のコードに相当する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);

しかし、ループがどの反復で行われているかを判断する方法が見つかりませんでした。どんな助けでもいただければ幸いです!

4

11 に答える 11

30

LINQにはメソッドがありませんがForEach、それには正当な理由があります。LINQはクエリを実行するためのものです。これは、いくつかのデータソースから情報を取得するように設計されています。データソースを変更するようには設計されていません。LINQクエリは副作用を引き起こしてはなりません。これは、まさにここで行っていることです。

Listクラスには、使用ているForEachメソッドがあります。実際にはSystem.Linq名前空間にないため、技術的にはLINQの一部ではありません。

forあなたの質問のループには何の問題もありません。あなたがしようとしている方法でそれを変えようとすることは(良い習慣の観点から)間違っているでしょう。

これは、問題をより詳細に説明するリンクです。

さて、そのアドバイスを無視してとにかくメソッドを使用したい場合は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++;
    }
}
于 2012-10-24T17:21:45.050 に答える
19

本当にList.ForEachを使用したい場合は、次のように簡単にできます。

//[...]
int i=0;
donations.ForEach(x => nvc.Add("item_name_" + i++, x.AccountName);
于 2016-08-05T17:19:33.137 に答える
12

少し複雑で、中間のコレクションを作成しますが、どうでしょうか。

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

これは、インデックスを組み込んだオーバーロードをEnumerable.Select使用します。

私は、このようにすることから実際に得るものは何もないと主張する必要があります。中間コレクションを使用するとオーバーヘッドが増え、IMHOは元のforループよりも読みやすくなります。

foreachの代わりにループを使用する場合は、中間コレクションをスキップすることもできますList.ForEach@wageogheの回答を参照してください(これも強くお勧めします)。

于 2012-10-24T17:24:21.597 に答える
10

これは古い投稿ですが、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;
});
于 2019-03-06T10:29:09.590 に答える
3

Dictionary<string, string>名前/キーが一意であるように見えるため、を使用していない理由はありますか?ToDictionaryこれはより高速で、標準のクエリ演算子を使用できます。

また、拡張メソッドを使用したい場合は(Servyがここでforループが正しい解決策であると言っていますが)、独自のメソッドを作成できます。ここを参照してください。

于 2012-10-24T17:28:40.450 に答える
3

@lcによる答えに便乗。

foreach (var x in donations.Select((d, i) => new {ItemName = "item_name_" + i, AccountName = d.AccountName}))
{
  nvc.Add(x.ItemName, x.AccountName);
}
于 2012-10-24T18:28:22.240 に答える
2

これは、aggregateを使用して行うこともできます。次の例を確認してください。

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つずつ増やして、それを返す必要があることです。

于 2020-01-13T15:04:23.937 に答える
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));
于 2018-11-22T10:46:25.183 に答える
-1

くだらない解決策は、単にselectを使用して、役に立たない値を返すことです。

items.toList().Select((el, index) =>
{
    el.doStuff();
    return 0;
});
于 2022-02-28T17:32:10.393 に答える
-1

このソリューションはすでにここにあるはずですが...LinqにSelectはインデックスが含まれているので、いつでもタプルにパックして繰り返すことができます。例えば:

foreach ((var item, int n) in TheItems.Select((i,n)=>(i,n))) {
    // item is the current item, n is its index
}

または、必要に応じて:

foreach (var element in TheItems.Select((item,n)=>(item,n))) {
    // element.item is the current item, element.n is its index
}

または、この回答に似ていますが、少し冗長ではありませんが、を呼び出すことで遅延評価が無効になることに注意してください。これにより、呼び出すToList()前にソース全体に列挙が強制されますForEach()

TheItems.Select((item,n)=>(item,n)).ToList().ForEach(element => { 
    // element.item is the current item, element.n is its index
});

いずれにせよ、アイテムインデックスを手動で計算する必要はまったくありません。

于 2022-03-05T04:18:49.023 に答える
-2

これを試して -

donations.ForEach(x =>
         {
             int index = donations.IndexOf(x);
             nvc.Add("item_name_" + index, x.AccountName);
         });
于 2012-10-24T17:26:48.560 に答える