15

私は多次元配列を持っています。その配列内の特定の要素を囲む要素を取得したいと考えています。

たとえば、次のような場合:

[[1,2,3,4,5,6]
 [8,9,7,5,2,6]
 [1,6,8,7,5,8]
 [2,7,9,5,4,3]
 [9,6,7,5,2,1]
 [4,7,5,2,1,3]]

上記の要素の周りにある 8 つの要素すべてを見つけるにはどうすればよいですか? また、エッジの要素をどのように処理すればよいでしょうか?

私が考え出した1つの方法は、これに9行のコードを書くことです。これは明らかですが、より良い解決策はありますか?

4

8 に答える 8

13

フォームで「方向配列」を使用できます

[[-1,-1], [-1,0],[1,0]..and so on]

ポイント座標を取り、方向配列を反復処理するメソッド -> 座標に方向番号を追加し、インデックスが範囲外でないことを確認して結果を収集します。このようなもの:

private static int[][] directions = new int[][]{{-1,-1}, {-1,0}, {-1,1},  {0,1}, {1,1},  {1,0},  {1,-1},  {0, -1}};

static List<Integer> getSurroundings(int[][] matrix, int x, int y){
    List<Integer> res = new ArrayList<Integer>();
    for (int[] direction : directions) {
        int cx = x + direction[0];
        int cy = y + direction[1];
        if(cy >=0 && cy < matrix.length)
            if(cx >= 0 && cx < matrix[cy].length)
                res.add(matrix[cy][cx]);
    }
    return res;
}
于 2012-10-05T10:01:39.137 に答える
5

(i, j) の場合 ->

              (i - 1, j - 1)
              (i - 1, j)
              (i - 1, j + 1)

              (i, j - 1)
              (i, j + 1)

              (i + 1, j - 1)
              (i + 1, j)
              (i + 1, j + 1)

これで、端で をチェックしnum % row == 0、次に行の端で... をチェックし、次にnum % col == 0列の端で..

続行する方法は次のとおりです。 -

インデックスを指定すると、 for 、 then 、 then に(i, j)隣接する行の要素を見つけることができます。(: - インデックスの場合は、アクセスするだけです。 )ji - 1ii + 1ij - 1j + 1

row edgeその後、とcolumn edge..も確認できます。

ここでは、以下のコードを見て、どのように発生するかを確認できます: -

    // Array size
    int row = 6;
    int col = 6;
    // Indices of concern
    int i = 4;
    int j = 5;

    // To the left of current Column
    int index = i - 1;
    for (int k = -1; k < 2; k++) {
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }
    }


    // In the current Column
    index = i;

    // Increment is 2 as we don't want (i, j)
    for (int k = -1; k < 2; k = k + 2) {            
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }
    }

    // To the right of current Column
    index = i + 1;
    for (int k = -1; k < 2; k++) {
        if (index % row > 0 && ((j + k)  % col) > 0) {
            System.out.println(arr[index][j + k]);
        }

    }

更新: - 上記のコードはさらに単純化できます..しかし、私はそのタスクをあなたに任せます.. ヒント: - そこから for ループを1つ減らすことができます..

于 2012-10-05T09:56:22.733 に答える
2
for (i = 0; i < array.length; i++) {
            for (j = 0; j < array[i].length; j++) {
                for (x = Math.max(0, i - 1); x <= Math.min(i + 1, array.length); x++) {
                    for (y = Math.max(0, j - 1); y <= Math.min(j + 1,
                            array[i].length); y++) {
                        if (x >= 0 && y >= 0 && x < array.length
                                && y < array[i].length) {
                            if(x!=i || y!=j){
                            System.out.print(array[x][y] + " ");
                            }
                        }
                    }
                }
                System.out.println("\n");
            }
        }

Thanks to all the people who have answered, but i figured it out with the help of this post which i found just now, and above is the solution. thanks again :)

于 2012-10-05T10:50:19.527 に答える
1

基本的なケースは、インデックスシフトによって隣接要素を取得することです。、、などに(i,j)なります。(i + 1, j)(i - 1, j)

エッジでは、2つのアプローチを使用します。

  1. 例外を回避するためのモジュロ%演算子IndexOutOfBoundsですが、間違った要素のインデックス付けと混同されることがあります。
  2. デフォルト要素の1つのレイヤーで行列をラップします。行列を保持するための余分なスペースが追加されますが、例外や多くのifなどをキャッチすることなくコードが読みやすくなります。このトリックは、迷路を行列として表現するときによく使用されます。

例:デフォルトの要素は0です。

0 0 0 0 0 0
0 1 2 3 4 0
0 2 6 7 3 0
0 1 3 5 7 0
0 2 4 6 2 0
0 0 0 0 0 0

注:拡張ではなく、実際の配列サイズを繰り返すことを忘れないでください。

于 2012-10-05T10:06:04.330 に答える
1

これは、Ruby で書かれた問題に対する私の解決策です。要素が端にあるかどうかを計算する代わりに、端を「超えて」要素にアクセスし、そこで発生する「nil」値または例外を処理できます。次に、最終リストから「nil」値を削除します。このソリューションは、ある「ポイント」がエッジを超えているかどうかを計算するほどには良くありません。

big_map = [[1,2,3,4,5,6],
           [8,9,7,5,2,6],
           [1,6,8,7,5,8],
           [2,7,9,5,4,3],
           [9,6,7,5,2,1],
           [4,7,5,2,1,3]]

# monkey patch classes to return nil.
[NilClass, Array].each do |klass|
    klass.class_eval do
        def [](index)
            return nil if index < 0 or index > self.size rescue nil
            self.fetch(index) rescue nil
        end
    end
end

class Array

    # calculate near values and remove nils with #compact method.   
    def near(i,j)
        [ self[i - 1][j - 1], self[i - 1][j - 0], self[i - 1][j + 1],
          self[i - 0][j - 1],                     self[i - 0][j + 1],
          self[i + 1][j - 1], self[i + 1][j - 0], self[i + 1][j + 1],
        ].compact
    end
end

puts big_map.near(1,1).inspect
# => [1, 2, 3, 8, 7, 1, 6, 8]

puts big_map.near(0,0).inspect
# => [2, 8, 9]

puts big_map.near(5,5).inspect
# => [2, 1, 1]
于 2012-10-05T11:07:08.817 に答える
-2
(x-1, y-1) -> upper left
(x-1, y) -> left
(x-1, y+1) -> lower left

(x, y+1) -> up
(x, y) -> current position
(x, y-1) -> down

(x+1, y+1) -> upper right
(x+1, y) -> right
(x+1, y-1) -> lower right

これをガイドとして使用できます。あとは、それらを try catch に追加するだけです。

 for( int x=0; x<arr.length; x++ ){
  for(int y=0; y<arr[x].length; y++){
  if( arr[x][y] == 8 ){
    try{
      System.out.println("Upper Left is: " + arr[x-1][y-1]);
    }catch(ArrayIndexOutOfBoundsException e){
     //do something
    }


    try{
      System.out.println("Left is: " + arr[x-1][y]);
    }catch(ArrayIndexOutOfBoundsException e){
     //do something
    }

    //.....and others
   }
  }
于 2012-10-05T10:13:38.900 に答える