web-dev-qa-db-fra.com

Rechercher des éléments entourant un élément dans un tableau

J'ai un tableau multidimensionnel, je veux obtenir les éléments entourant un élément particulier dans ce tableau. 

Par exemple si j'ai les éléments suivants:

[[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]]

Comment trouver tous les 8 éléments autour de l'un des éléments ci-dessus? Et comment puis-je prendre soin des éléments sur les bords? 

Une façon dont j'ai compris est d'écrire un code à 9 lignes pour cela, ce qui est évident, mais existe-t-il une meilleure solution?

15
md1hunox
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");
            }
        }

Merci à toutes les personnes qui ont répondu, mais j’ai compris avec l’aide de ce post que j’ai trouvé tout à l’heure, c’est la solution ci-dessus. Merci encore :)

2
md1hunox

Vous pouvez utiliser 'direction array' dans la forme

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

Et méthode qui prend la coordonnée de point et itère dans le tableau de direction -> ajoute des numéros de direction aux coordonnées, vérifie que les index ne sont pas hors limites et collecte les résultats. Quelque chose comme ceci:

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;
}
8
zvez

Pour (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)

Maintenant, sur les bords, vous pouvez rechercher num % row == 0, puis sa ligne Edge ... Et num % col == 0 puis sa colonne Edge ..

Voici comment procéder: -  

Avec un index (i, j) .. Vous pouvez trouver des éléments dans les lignes adjacentes à j pour i - 1, puis i et ensuite i + 1. (NOTE: - pour l'index i, il vous suffit d'accéder à j - 1 et à j + 1)

Ensuite, vous pouvez également rechercher le row Edge et le column Edge ..

Ici, vous pouvez regarder le code ci-dessous, comment cela peut arriver: - 

    // 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]);
        }

    }

UPDATE: - Le code ci-dessus peut encore être simplifié .. Mais je vous laisse cette tâche .. HINT: - Vous pouvez en réduire une pour cette boucle. .

4
Rohit Jain

Le cas de base consiste simplement à obtenir des éléments voisins en indexant le décalage. Pour (i,j) ce sera (i + 1, j), (i - 1, j), etc. 

J'utilise deux approches sur les bords:

  1. Modulo % pour éviter une exception IndexOutOfBounds, mais il confond parfois avec une indexation erronée des éléments.
  2. Enveloppez votre matrice avec une couche de éléments par défaut . Il ajoute un espace supplémentaire pour contenir des matrices, mais rend votre code plus lisible sans attraper l'exception, beaucoup si et ainsi de suite. Cette astuce est souvent utilisée lorsque la représentation labyrinthe est une matrice.

Exemple: votre élément par défaut est 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

Remarque: n'oubliez pas de parcourir la taille réelle la taille du tableau, non étendue.

1
mishadoff

Ceci est ma solution pour votre problème écrit en Ruby. Au lieu de calculer si l'élément est sur Edge, vous pouvez accéder aux éléments "sur" Edge et gérer les valeurs "nil" ou les exceptions qui s'y produisent. Supprimez ensuite les valeurs "nil" de la liste finale. Cette solution n’est pas aussi efficace que de calculer si un "point" est au-dessus du bord ou non.

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]
1
Oto Brglez

Je travaillais sur le même problème et je proposais une petite solution optimisée pour trouver les nombres environnants de tout point dans une matrice 2D. J'espère que cela vous aidera. S'il vous plaît, commentez si je peux raccourcir quelque peu la logique Code: -

import Java.util.ArrayList;

public class test {
    public static void main(String[] arg){

        int[][] arr = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}};
        //int[][] arr = {{width,2,3},{4,5,6},{7,8,9}};
        ArrayList<Integer> al = new ArrayList<Integer>();
        int x = 2, y = 2;
        int width = 2; //change the value of width, according to the requirement 
        for(int i = 0; i < 5; i++){
            for(int j = 0; j < 5; j++){
                if( (i == (x-width) && ( (y+width) >= j && j >= (y-width))) || (i == (x+width) && ( (y+width) >= j && j >= (y-width))) || (j == (y-width) && ( (x+width) >= i && i >= (x-width))) || (j == (y+width) && ( (x+width) >= i && i >= (x-width)))  ){
                    //if( x >= 0 && i < (i+width) && y >= 0 && j < (j+width))
                        {
                        al.add(arr[i][j]);
                        }
                }
            }
        }
        System.out.println(al);
    }

}
0
Varun Iyer

Vous n'avez pas mentionné si vous voulez des voisins cycliques pour les arêtes ou si vous ignorez les voisins cycliques. En supposant que vous vouliez des voisins cycliques, voici le code,

List<Integer> getNeighbours(int[][] mat, int x, int y){
  List<Integer> ret = new ArrayList<Integer>();
  int rows = mat.length;
  int cols = mat[0].length;
  for(int i=-1,i<=1;i++)
    for(int j=-1;j<=1;j++)
      if(i||j) ret = ret.add(mat[(x+i)%rows][(y+j)%cols]);
  return ret;
}
0
ishandutta2007