我有三个相同长度的数组,我希望使用.Zip选项提取最大/最小(或应用任何其他函数 Fct ),任何人都可以帮助我在干净的方式?
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)然后< strong> Fct(Fct(a,b),c)当Fct不一定在该sens中可分裂时。
答案 0 :(得分: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();
...
}
玩得开心:)
答案 1 :(得分:0)
以下函数是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());
}