2012-10-05 4 views
14

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

Par exemple, si je donne les résultats 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 puis-je 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 de 9 lignes pour cela, ce qui est évident, mais y at-il une meilleure solution?

+6

Utilisez modulo (''%) pour prendre soin des cas sur les bords ... – Baz

Répondre

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

Merci à tous ceux qui ont répondu, mais je me suis dit il avec l'aide de this post que je trouve tout à l'heure, et au-dessus est la solution. merci encore :)

+0

@vineetrok .. Bien que vous avez trouvé une solution .. Mais pourquoi n'avez-vous pas fait la recherche avant de poster la question ici ?? –

+1

oui je l'ai fait, mais j'utilisais ce mot "entourant" des éléments, le moment j'ai utilisé "voisin" j'ai obtenu la réponse dans une autre question: p – md1hunox

+0

@vineetrok .. OK .. alors vous pouvez accepter une réponse pour marquer cette question résolu .. –

4

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 vérifier num % row == 0, puis son bord à la ligne ... et, num % col == 0 puis son bord de colonne. .

Voici comment vous pouvez procéder: -

Étant donné un indice (i, j) .. vous pouvez trouver des éléments dans une ligne adjacente à j pour i - 1, puis i, puis i + 1. (NOTE: - pour l'index i il vous suffit d'accéder j - 1 et j + 1)

Par la suite, vous pouvez également vérifier la row edge et column edge ..

Ici, vous pouvez regarder le code ci-dessous, comment il 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]); 
     } 

    } 

MISE à JOUR: - Le code ci-dessus peut en outre être simplifié .. Mais je laisse cette tâche à vous .. TRUC: - Vous pouvez réduire une boucle à partir de là ..

+0

Semble il y a quelques '1's qui devraient être soit' i 'ou' j' (cas 2 et cas 7). – Baz

+0

@Rohit Jain: merci, je l'ai compris, mais, chose que je dois faire pour tous les éléments de la matrice multidimensionnelle, donc j'ai besoin de trouver un moyen généralisé de traverser tous les éléments voisins – md1hunox

+1

@vineetrok Si vous changez chaque '(i, j)' à '(i% rows, j% cols)' cela fonctionnera comme un cas général. – Baz

8

Vous pouvez utiliser « tableau de direction » sous forme

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

Et méthode qui prend point de coordonnées et itère à travers le tableau de direction -> ajouter direction numéros de coordonnées, vérifier les index ne sont pas hors limites et de recueillir des 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; 
} 
+0

Salut, belle solution. Est-il possible d'étendre cela à, par exemple, obtenir les éléments environnants autour d'un ensemble interne d'éléments environnants d'un seul indice? Merci. – Unheilig

1

cas de base est juste pour obtenir des éléments voisins par déplacement d'indexation. Pour (i,j) il sera (i + 1, j), (i - 1, j), etc.

Sur les bords j'utilise deux approches:

  1. opérateur Modulo % pour éviter IndexOutOfBounds exception, mais il confond parfois avec mauvaise indexation des éléments.
  2. Enveloppez votre matrice avec une couche de éléments par défaut.Il ajoute des extraspace pour contenir des matrices, mais rend votre code plus lisible sans attraper d'exception, beaucoup ifs et ainsi de suite. Cette astuce souvent utilisée lorsque la représentation maze en tant que 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 

Note: ne pas oublier itérer taille réelle tableau, pas étendu.

-1
(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 

Vous pouvez l'utiliser comme guide. Maintenant, tout ce que vous avez à faire est de les ajouter dans un essai.

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 
    } 
    } 
+0

Attraper 'Exception' est un très mauvais style. Utilisez la sous-classe appropriée ... – Baz

+0

Vous devriez faire la vérification des limites en utilisant l'opérateur 'modulo (%)'. Vous n'avez pas besoin de blocs 'try-catch' pour cette chose .. –

+0

@gekkostate Si vous changez l'exception, pourquoi ne pas changer l'autre aussi? – Baz

1

Ceci est ma solution pour votre problème écrit en Ruby. Au lieu de calculer si l'élément est au bord, vous pouvez accéder aux éléments "au-dessus" du bord et gérer les valeurs "nuls" ou les exceptions qui s'y produisent. Ensuite, supprimez les valeurs "nil" de la liste finale. Cette solution n'est pas aussi bonne que de calculer si un "point" est sur le 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] 
0

je travaillais sur lui même problème et est venu avec une petite solution optimisée pour trouver les numéros autour d'un point quelconque dans une matrice 2D, espérons que cette aide, s'il vous plaît commentaire si je peux raccourcir la logique en quelque sorte 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

Vous n'avez pas mentionné si vous voulez des voisins cycliques pour les bords ou ignore les voisins cycliques. En supposant que vous voulez voisins cycliques est le code ici,

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; 
} 
Questions connexes