算法:检查3D数组中的条件

时间:2013-05-08 15:35:25

标签: c# arrays algorithm list

这个很难解释!对不起,但是这里...... 我有一些数据[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个对象

等等更多条件,导致列表越来越小。 它们的执行顺序无关紧要。 我有点知道怎么做,但我最终陷入了一些非常讨厌的循环...... 有任何想法吗?也许添加到另一个列表比从原始列表中删除更快? 提前谢谢!

1 个答案:

答案 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);