1

.Zip オプションを使用して最大/最小値を抽出したい (または他の関数Fctを適用したい) 同じ長さの 3 つの配列があります。

double [] x = new  double []  {1,3,5,6,6};
double [] y = new  double [] {5,6,8,3,4} ;
double [] z = new  double  [] {9,4,10,0,8} ;
double []  result = z.Zip(x.Zip(y, (a, b) => Math.Max(a, b)).ToList(), (c, maxab) => Math.Max(c, maxab)).ToArray();

{double[5]}
[0]: 9.0
[1]: 6.0
[2]: 10.0
[3]: 6.0
[4]: 8.0

私の質問は次のとおりです: Fct (a,b,c)を2回実行する代わりに、Fct (a,b) then Fct ( Fct (a,b),c)を実行する方法はありますか?それは感じます。

4

2 に答える 2

1

改善された回答(構文上の喜びのため):

static IEnumerable<T> Map<T>(Func<IEnumerable<T>, T> f, 
                             params IEnumerable<T>[] arr)
{
  var enums = Array.ConvertAll(arr, x => x.GetEnumerator());
  try
  {
    while (enums.All(x => x.MoveNext()))
    {
      yield return f(enums.Select(x => x.Current));
    }
  }
  finally
  {
    foreach (var e in enums) e.Dispose();
  }
}

static void Main(string[] args)
{
  double[] w = { 1, 2, 3, 4, 5 };
  double[] x = { 1, 3, 5, 6, 6 };
  double[] y = { 5, 6, 8, 3, 4 };
  double[] z = { 9, 4, 10, 0, 8 };

  var r = Map(Enumerable.Max, w, x, y, z).ToArray();

  ...
}

楽しむ :)

于 2012-11-16T11:01:19.400 に答える
0

次の関数は、3 つのコレクションに対して実行される Zip 関数のテスト済みバージョンです。一度にすべての結果を計算するわけではありませんが、Linq の Zip 関数と同様に遅延実行を使用します。

static class ThreeWayZip
{
  public static IEnumerable<TResult> Zip3<TFirst, TSecond, TThird, TResult>(
      this IEnumerable<TFirst> first,
      IEnumerable<TSecond> second,
      IEnumerable<TThird> third,
      Func<TFirst, TSecond, TThird, TResult> resultSelector)
  {
    if(first == null || second == null || third == null) 
    { throw new ArgumentNullException(); }

    using (var iterator1 = first.GetEnumerator())
    using (var iterator2 = second.GetEnumerator())
    using (var iterator3 = third.GetEnumerator())
    {
      while(iterator1.MoveNext() 
        && iterator2.MoveNext()
        && iterator3.MoveNext())
      {
        yield return resultSelector(
          iterator1.Current, iterator2.Current, iterator3.Current);
      }

    }
  }
}

私が実行したテストは次のとおりです。

int Min3(int x, int y, int z) 
{
      if(x<=y)
      {
        if(x<=z)
        { //x<=z && x<=y
          return x;
        }
        //z<x && x<=y 
        return z;
      }
      //y<x
      if(z<=y) return z;
      //y<z && y<x
      return y;
}

[TestMethod]
public void Test_Zip3()
{
  int[] a = { 2, 3, 5 };
  int[] b = { 3, 2, 5 };
  int[] c = { 5, 1, 5 };

  IEnumerable<int> result = a.Zip3(b, c, Min3);
  CollectionAssert.AreEqual(new[] {2, 1, 5}, result.ToArray());
}

[TestMethod]
public void Zip_With_Different_ArrayLength()
{
  int[] a = { 2, 3, };
  int[] b = { 3, 2, 5 };
  int[] c = { 5, 1, 5, 8 };

  var result = a.Zip3(b, c, Min3);
  CollectionAssert.AreEqual(new[] {2, 1}, result.ToArray());
}

[TestMethod]
public void Zip_With_EmptyArray()
{
  int[] a = { 2, 3, };
  int[] b = { 3, 2, 5 };
  int[] c = { };

  var result = a.Zip3(b, c, Min3);
  CollectionAssert.AreEqual(new int[0], result.ToArray());
}

[TestMethod]
public void Zip_With_First_ArrayEmpty()
{
  int[] a = { };
  int[] b = { 3, 2, 5 };
  int[] c = { 1, 8, };

  var result = a.Zip3(b, c, Min3);
  CollectionAssert.AreEqual(new int[0], result.ToArray());
}


[TestMethod]
public void Zip_With_All_Arrays_Empty()
{
  int[] a = { };
  int[] b = { };
  int[] c = { };

  var result = a.Zip3(b, c, Min3);
  CollectionAssert.AreEqual(new int[0], result.ToArray());
}
于 2012-11-16T11:54:27.407 に答える