2009-09-11 9 views
11

私はlinq式(好ましくはlambdas)に変えてデリゲートとして使いやすくするコードを少し用意しています。コードは次のようになります。私の人生のために配列のすべての値を指定した値に設定するLinq式

List<DateTime[]> changes = new List<DateTime[]>(); 
changes = PopulateChanges(); 
for (int i = 0; i < changes.Count; i++) 
{ 
    for(int j = 0; j < changes[i].Length; j++) 
    { 
     changes[i][j] = DateTime.MinValue; 
    } 
} 

、私はこの1つを把握するように見えることはできません。 ForEachやさまざまな形式のselectなどを試してみました。何も正しく動作しないようです。

私はDateTimeのデフォルト値がMinValueであることを知っていますが、実際にはすでに設定されていればデフォルトにリセットされています。

作業表現を教えてもらえますか?

EDIT:

私は本当に私が指定された値に多次元配列のすべての要素を設定するための簡潔な方法をしたいされ、ここで言ってどうなったと思います。確かに、ネストされたforループは機能しますが、私はそれを関数に置くことができます(私はすでに行っています)。私は、複数行のモンスターを作成せずにデリゲートでより簡単に使用できるように、より簡潔なものを求めています。

答えて

14

これはトリックを行う必要があります。

これはLINQではなく、ネストされたforループとほとんど違いはありませんが、少し冗長ではありません。

changes.ForEach(x => Array.Clear(x, 0, x.Length)); 

(ab)LINQを使用して同じ結果を得る方法はありますが、私はそれらを汚いハックとみなしています。その上、LINQの同等物はおそらく上記の私の例よりもあまり冗長ではありません。

+0

私はこれが好きです。私のために十分に近いと思う。 –

2

LINQは実際にコレクションを更新するためのものではありません。 これはクエリに関するものです。つまり、既存のコレクションの上に列挙型を作成します。 あなたのコードは完全に読み込み可能で、ラムダなどがたくさんある場合は、あまり改善されません。

あなたが値に設定し、各要素を新しいList<DateTime[]>を作成したい場合は、あなたがこれを行うことができます:

var changes = Enumerable.Range(0, width) 
         .Select(x => Enumerable.Range(0, height) 
               .Select(y => DateTime.MinValue) 
               .ToArray()) 
         .ToList(); 

あなたはが本当にForEach/LINQを使用してそれを実行したい場合は、それが乱用することが可能です

changes.ForEach(array => array.Select((dt, i) => array[i] = DateTime.Now) 
           .LastOrDefault()); 
+0

私が本当に理解できない理由は、これが意味するものではないということです。データをクエリして値を更新する典型的なLinq2SQLクエリについて考えてみましょう。これはどう違うのですか? –

+3

LINQ2SQLを使用してデータベースにクエリを行い、返されたオブジェクトを変更します。返されたすべてのオブジェクトを変更する場合は、ループを使用してオブジェクトを反復処理する必要があります。オブジェクトを含む列挙型はまったく変更されません。 LINQはクエリに関するものであり、コレクションの更新に関するものではありません。 – dtb

2

興味深い質問を、しかし、LINQの約を照会であり、あなたはここで何をやっている:Select(しかし、私はそれをお勧めしません)私の質問によく似ていません。そこに解決策があるとしても、私はLinqをこのようなものに使うのかどうかはわかりません。

+1

私はそれに反して、実際にはクエリですが、副作用のあるクエリです。 List のすべての要素を返すようにクエリを実行していますので、これらの値を設定できます。 Linqには、transofrmationの投影などのような多くのクエリがあります。私はこれがどのように異なっているかは実際には分かりません。 –

+4

照会されたコレクション(したがって "照会")を変更するLINQ内の単一の照会はありません。 – dtb

+0

オリジナルを変更するものは何もありませんが、彼が達成しようとしていることはできると思います... – bytebender

0

上記のデリゲートをどのように使用することを提案するかについて、いくつかのユースケースを説明できますか?

PopulateChanges()がDateTime配列のList <>を返す場合、それらをすべて通過してDateTime.MinValueに設定している場合は、挿入するコード単位デリゲート?

+0

私がやっているのは、私のFYIが言っているように、実際の例を作成することだけです。私は実際にはこれとは別の領域で、それのforループ部分(残りはちょうどセットアップです)をキャリングしています。私はデータを含む別のリストを持っています。これは文字列配列の各要素を最後に変更された時刻にマッピングします。変更がクリアされると、時刻をMinValueにリセットする必要があります。新しい変更が発生すると、それらの要素は新しいDateTimeを取得します。 –

0

あり、常にベストプラクティスなどですが、私は誰もが言ったすべてに同意する場合、私は私が正しくあなたを理解していれば、あなたはいくつかの異なった理由のためにあなたのネストされた配列を列挙しなければならない...

を知らないと

...私はこのようにそれを行うだろう
List<DateTime[]> changes = new List<DateTime[]>(); 
changes = PopulateChanges(); 

// *** As pointed out ForEach this will not change the value in the array, Thanks!*** 
changes.ForEach(change => change.ToList().ForEach(date => date = DateTime.MinValue)); 

// this how ever works but is kind of confusing... 
changes = changes.Select(change => change.Select(date => DateTime.MinValue).ToArray()).ToList(); 
//Even that would get old writing it over and over again... 

...そこを達成するには、いくつかの異なる方法があるが、ここでLINQとアウトを持つものを使用して1 ..です再利用するためにその機能をカプセル化したいと思います
private void ForEachOnNestedDates(List<DateTime[]> list, Func<DateTime, DateTime> method) 
{ 
    // Use your code... 
    for (int i = 0; i < list.Count; i++) 
    { 
     for(int j = 0; j < list[i].Length; j++) 
     { 
      list[i][j] = method.Invoke(list[i][j]); 
     } 
    } 
} 

これにより、これを再利用して各アイテムに異なる作業を行うことができます。例。

//Add a Day to each datetime value 
ForEachOnNestedDates(changes, (DateTime date) => date.AddDays(1)); 

//You also make it even more readable 
ForEachOnNextedDates(changes, DoSomethingWithDate); 

private DateTime DoSomethingWithDate(DateTime value) 
{ 

} 

これは、各日付の時間で行う事とは対照的に、各日付の時刻に行わ事のために使用される...それは少し異なるだろう。

+2

ラムダのパラメータに値を代入してもクエリされたコレクションは変更されません。 – dtb

+0

私は修正しました。 2番目のオプションはうまくいくはずです... – bytebender

関連する問題