这个很难解释!对不起,但是这里...... 我有一些数据[X] [Y] [Z]的3D数组,我想检查大约10种不同的组合条件,只保留匹配时的数据......例如:
X Y Z
//myData[1..1000000][1..10][1..10].foo // foo is an int
X[i].Y[ii].Z[iii].foo; // X is a container, Y= 1 to 10 levels. And Z= objects
//I want to apply a "filter" to the Z objects...
假设我想找到“foo”总和小于和大于两个数字的所有组合,并且只保留那些Z对象
对于下一次迭代,我想找到只说“foo”是素数的地方,仍然只保留Z个对象
等等更多条件,导致列表越来越小。 它们的执行顺序无关紧要。 我有点知道怎么做,但我最终陷入了一些非常讨厌的循环...... 有任何想法吗?也许添加到另一个列表比从原始列表中删除更快? 提前谢谢!
答案 0 :(得分:2)
当你想把这样的逻辑链接在一起时,我想你真的想要使用Linq。不幸的是,在多维数组上使用Linq可能很麻烦。但是,通过一些辅助方法,我们可以将数据数组转换为更有用的数据。首先,让我们为任何具有3个维度的对象构建一个包装类:
public class ThreeDimensionalArrayExtension<T> {
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public T Value { get; set; }
}
接下来,让我们编写一个帮助方法,将三维数组转换为新类型的IEnumerables:
public static class ThreeDimensionalArrayExtensionMethods {
public static IEnumerable<ThreeDimensionalArrayExtension<T>> ConvertArray<T>(this T[,,] foos) {
for(var x = 0; x < foos.GetLength(0); x++) {
for (var y = 0; y < foos.GetLength(1); y++) {
for (var z = 0; z < foos.GetLength(2); z++) {
yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x, y, z] };
}
}
}
}
}
请注意,由于我们使用的是迭代器块(yield-return模式),因此调用此方法实际上不会执行任何计算。
现在我们可以在你的三维数组上使用Linq的强大功能来过滤它,但我们想要它!
myData.ConvertArray().Where(d => d.Value.Foo > 5)
.Where(d => IsPrime(d.Value.Foo))
.Where(...);
编辑: 我看到你使用的是3个嵌套类,而不是我假设你使用的多维数组。目标应该仍然是将该对象转换为IEnumerable,您可以非常轻松地链接Linq查询以过滤或投影数据。在您的情况下,您可以这样做:
public static class ThreeDimensionalArrayExtensionMethods {
public static IEnumerable<ThreeDimensionalArrayExtension<X>> ConvertArray(this X[] foos) {
for(var x = 0; x < foos.Count(); x++) {
for (var y = 0; y < foos[x].Count(); y++) {
for (var z = 0; z < foos[x][y].Count(); z++) {
yield return new ThreeDimensionalArrayExtension<T> { X = x, Y = y , Z = z, Value = foos[x][y][z] };
}
}
}
}
}
然后对ConvertArray使用相同的调用,然后过滤上面描述的Where子句。
如果您不关心X / Y / Z索引,您也可以使用SelectMany
将多维列表投影到一维列表中:
X.SelectMany(y => y.SelectMany(z => z)).Where(z => z.Foo > 5);