如何在Java中从二维数组中删除占位符值



我有一个包含正整数和负整数的int[][][]a。我只想将正整数复制到另一个数组中,int[][]result。这是我的尝试:

for( int r = 0; r < a.length; r ++ )
        {
            int aC = 0;
            for( int resC = 0; resC < result[r].length; resC++ )
            {
                while (a[r][aC] < 0)
                {
                    aC++;
                }
                result[r][resC] = a[r][aC];
                aC++;
            }
        }

当我运行程序时,它在第6行崩溃,引用了一个java.lang.ArrayIndexOutOfBoundsException: 3错误。当我运行调试器时,我可以看到只要r=0,它就可以工作。

我觉得我错过了一些显而易见的东西,但盯着它看了一个小时后,我仍然找不到问题所在。

为什么有3个循环?只需循环2个维度并复制正值:

for (int r = 0; r < a.length; r++)
    for (int c = 0; c < a[r].length; c++)
        if (a[r][c] > 0)
            result[r][c] = a[r][c];

当然,除非你想浓缩这些值(问题没有说,但代码尝试似乎表明了这一点)。或者您也想截断?

  Input              Copy            Condensed        Truncated
-1  1   2           0  1  2           1  2  0           1  2
-1  -1  3    ==>    0  0  3    ==>    3  0  0    ==>    3
4   -1  5           4  0  5           4  5  0           4  5

这里有一个截断的版本:

int[][] result = new int[a.length][];
for (int r = 0; r < a.length; r++) {
    int count = 0;
    for (int c = 0; c < a[r].length; c++)
        if (a[r][c] > 0)
            count++;
    result[r] = new int[count];
    for (int c = 0, cRes = 0; c < a[r].length; c++)
        if (a[r][c] > 0)
            result[r][cRes++] = a[r][c];
}

当我们到达内部CCD_ 2循环时,我们对CCD_ 3没有任何保证,因此CCD_ 4很可能是越界的。取而代之的是:

    for (int r = 0; r < a.length; r++) {
        int aC = 0;
        for (int resC = 0; resC < result[r].length; resC++) {

代码将更安全,如下所示:

    for (int r = 0; r < a.length; r++) {
        int aC = 0;
        for (int resC = 0; resC < a[r].length; resC++) {

因为,我们知道a[r]将在边界内。

但这还远远不够。最里面的while循环也可能试图访问越界的索引,事实上,当您至少有一个负值时,这是不可避免的。实际上,你需要反转那里的循环逻辑,而不是在结果中对索引进行迭代,对源代码中的索引进行迭代会更有意义。像这样:

    for (int r = 0; r < a.length; r++) {
        int resC = 0;
        for (int aC = 0; aC < a[r].length; aC++) {
            if (a[r][aC] < 0) {
                continue;
            }
            result[r][resC++] = a[r][aC];
        }
    }

最后,通过重命名变量,可以更容易地理解代码试图做什么:

    for (int row = 0; row < source.length; row++) {
        int targetCol = 0;
        for (int col = 0; col < source[row].length; col++) {
            if (source[row][col] < 0) {
                continue;
            }
            target[row][targetCol++] = source[row][col];
        }
    }

在上没有边界检查

a[r][aC]

所以

while (a[r][aC] < 0)

将失败。

同样,由于现在的数组大小不均匀,最好将其添加到ArrayList中,然后在必要时转换为数组。

类似的东西

ArrayList <Integer> posValues = new ArrayList <Integer> ();
for( int r = 0; r < a.length; r ++ )
{
        for( int c = 0; c < a[r].length; c++ )
        {
            if (a[r][c] > 0)
            {
                posValues.add (new Integer (a[r][c]));
            }
        }
 }

最新更新