LINQによる複数の配列の扱い

タグの編集
投稿者 threecourse  (社会人) 投稿日時 2010/7/9 00:38:22
LINQによる複数の配列の扱いに、良いやり方がないかと思い、投稿しました。

例えば、
「2つの配列の要素の和を要素とする配列」を返す関数が必要で、以下のように書いたのですが、
これをLINQなどを使って簡潔に書きたいと思っています。

    Function AddElements(ByVal ary1() As DoubleByVal ary2() As DoubleAs Double()
        Dim aryreturn(ary1.length - 1) As Double
        For i = 0 To ary1.length - 1
            aryreturn(i) = ary1(i) + ary2(i)
        Next i
        Return aryreturn
    End Function


たとえば、配列の各要素にvalueを加える関数は以下のように書けるのですが、
このようには書けないものでしょうか?

    Function AddValue(ByVal ary1() As DoubleByVal value As DoubleAs Double()
        Return (From e In ary1 Select e + value).ToArray
    End Function


よろしくお願いします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/7/9 01:49:32
ary1 と ary2 の要素数が違っていた場合には、どのように扱うのでしょうか?

> これをLINQなどを使って簡潔に書きたいと思っています。
Function AddElements(ByVal ary1() As DoubleByVal ary2() As DoubleAs Double()
  Return ary1.Select(Function(e, i) e + ary2(i)).ToArray()
End Function

Sub Main()
  Dim a() As Double = {1,2,3,4}
  Dim b() As Double = {20,30,40,50}
  Array.ForEach(AddElements(a, b), AddressOf Console.WriteLine)
End Sub
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2010/7/9 10:27:34
>> aryreturn(i) = ary1(i) + ary2(i)
> ary1 と ary2 の要素数が違っていた場合には、どのように扱うのでしょうか?

要素数が異なる場合には、単純に ArgumentOutOfRangeException あたりを Throw しても
良いのかもしれませんが、一例として見つからなかった要素を 0.0 として扱うパターンを考えてみました。

'ary1.Length を優先する 
Function AddElements2(ByVal ary1() As DoubleByVal ary2() As DoubleAs Double()
  Return ary1.Select(Function(e, i) e + ary2.ElementAtOrDefault(i)).ToArray()
End Function

'要素数が異なる場合、不足している方は 0.0 として扱う 
Function AddElements3(ByVal ary1() As DoubleByVal ary2() As DoubleAs Double()
  Return (From i In Enumerable.Range(0, Math.Max(ary1.Length, ary2.Length)) _
          Select ary1.ElementAtOrDefault(i) + ary2.ElementAtOrDefault(i)).ToArray()
End Function
投稿者 threecourse  (社会人) 投稿日時 2010/7/10 00:43:38
魔界の仮面弁士さん、どうもありがとうございました、
なぜ上手くいくのかしばらくわからなかったのですが、要素のインデックス付きのselectがあるのですね。
http://msdn.microsoft.com/ja-jp/library/bb534869.aspx
ちなみに、これはクエリ式で書くことはできないのでしょうか?

今回考えているのは、要素数が同じであるべきなので、例外を投げるので良いと考えていました。
AddElement3を参考に、以下のようにして見ようと思います。

Function AddElement(ByVal ary1 As Double(), ByVal ary2 As Double()) As Double()
    If ary1.Length <> ary2.Length Then Throw New ArgumentOutOfRangeException
    Return (From i In Enumerable.Range(0, ary1.Length) Select ary1(i) + ary2(i)).ToArray
End Function