2012-11-16 51 views
1

我有三个相同长度的阵列,我想从中提取最大值/最小值(或应用任何其他功能Fct)使用.Zip可选性,任何人都可以帮助我以干净的方式做到这一点?使用.Zip C#应用功能列表#

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)而不是做了两遍:FCT(A,B)然后FCT(FCT(A, b),c)当Fct不一定在该sens中可分裂时。

回答

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

    ... 
} 

玩得开心:)

0

下面的函数,对三个集合运行压缩功能的测试版本,它不计算所有结果一次,但使用延迟执行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()); 
}