2012-10-05 18 views
14

Ho una matrice multidimensionale, voglio ottenere gli elementi che circondano un particolare elemento in quella matrice.Trova elementi che circondano un elemento in una matrice

Per esempio, se ho il seguente:

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

Come faccio a trovare tutti gli 8 elementi intorno qualsiasi degli elementi di cui sopra? E come mi prendo cura degli elementi ai bordi?

Un modo per capire è scrivere un codice a 9 righe per questo, che è ovvio, ma esiste una soluzione migliore?

+6

Usa modulo ('%') per prendersi cura dei casi ai bordi ... – Baz

risposta

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

Grazie a tutte le persone che hanno risposto, ma ho pensato che con l'aiuto di this post che ho trovato solo ora, e soprattutto è la soluzione. grazie ancora :)

+0

@vineetrok .. Bene che hai trovato una soluzione .. Ma perché non hai fatto la ricerca prima di postare la domanda qui ?? –

+1

sì, ma stavo usando questa parola "circostante" elementi, nel momento in cui ho usato "vicino" ho ottenuto la risposta in un'altra domanda: p – md1hunox

+0

@vineetrok .. OK .. allora puoi accettare una risposta per segnare questa domanda risolto .. –

4

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

Ora, ai bordi, è possibile verificare la presenza di num % row == 0, allora la sua fila a bordo ... e, num % col == 0 quindi il bordo della colonna. .

Ecco è come si può procedere: -

Dato un indice di (i, j) .. si possono trovare elementi in una riga adiacente a j per i - 1, quindi i e quindi i + 1. (NOTA: - per l'indice i basta accedere j - 1, e j + 1)

Successivamente si può anche verificare la row edge e column edge ..

Qui, si può guardare il codice qui sotto, come può accadere: -

// 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: - Il codice di cui sopra può essere ulteriormente semplificata .. Ma lascio questo compito a voi .. SUGGERIMENTO: - È possibile ridurre un ciclo for da lì ..

+0

sembra che ci siano alcuni '1's che dovrebbero essere sia i' 'o' j' (caso 2 e caso 7). – Baz

+0

@Rohit Jain: grazie, l'ho capito, ma, la cosa è che devo fare questo per tutti gli elementi della matrice multidimensionale, quindi ho bisogno di capire un modo generalizzato attraversare tutti gli elementi confinanti – md1hunox

+1

@vineetrok Se si modifica ogni '(i, j)' a '(i% rows, j% cols)' funzionerà come un caso generale. – Baz

8

È possibile utilizzare 'direzione della schiera' in forma

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

E metodo che prende coordinate punto e scorre serie direzione -> aggiungi direzione numeri per coordinate, controllare gli indici non sono fuori limite e raccogliere risultati. Qualcosa di simile a questo:

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

Ciao, bella soluzione. È possibile estenderlo, ad esempio, ottenendo gli elementi circostanti attorno ad un insieme interno di elementi circostanti di un singolo indice? Grazie. – Unheilig

1

Caso base è solo per ottenere elementi vicini di indicizzazione spostamento. Per (i,j) sarà (i + 1, j), (i - 1, j), ecc

Sui bordi io uso due approcci:

  1. Modulo % operatore per evitare IndexOutOfBounds eccezione, ma a volte confondere con elementi sbagliato indicizzazione.
  2. Avvolgere la matrice con uno strato di elementi predefiniti.Aggiunge alcune estensioni per contenere le matrici, ma rende il codice più leggibile senza interferire con le eccezioni, i lotti se e così via. Questo trucco è spesso usato quando la rappresentazione è labirinta come matrice.

Esempio: il vostro elemento di default è 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 

Nota: non dimenticate iterano effettiva dimensione matrice, non concessa.

-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 

È possibile utilizzare questo come guida. Ora tutto ciò che devi fare è aggiungerli in un 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 
    } 
    } 
+0

Catching 'Exception' è molto cattivo stile. Utilizzare la sottoclasse appropriata ... – Baz

+0

Si dovrebbe eseguire il controllo dei confini usando l'operatore 'modulo (%)'. Per questa cosa non sono necessari i blocchi 'try-catch' .. –

+0

@gekkostate Se si modifica l'eccezione, perché no cambia anche l'altro? – Baz

1

Questa è la mia soluzione per il tuo problema scritto in Ruby. Invece di calcolare se l'elemento è a bordo, è possibile accedere agli elementi "oltre" il bordo e gestire i valori "nil" o le eccezioni che si verificano lì. Quindi rimuovere i valori "nil" dall'elenco finale. Questa soluzione non è buona come calcolare se qualche "punto" è oltre il limite o meno.

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

stavo lavorando su lui stesso problema e si avvicinò con una piccola soluzione ottimizzata per trovare i numeri circostanti di qualsiasi punto in una matrice 2D, speriamo che questo aiuta, si prega di commentare se posso accorciare la logica in qualche modo Codice : -

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

Non si è detto se si desidera che i vicini ciclici abbiano margini o ignori i vicini ciclici. Supponendo che si desidera vicini ciclici Ecco il codice,

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; 
} 
Problemi correlati