How to find the neighbors of an element (8 neighbors - vertically, horizontally, diagonally) in a two-dimensional array, provided that neighbors can be searched through the border of the array?

There is a two-dimensional array, such as

enter image description here

To find the neighbors of an element inside an array, everything is simple. We combine the coordinates of the current element with the unit and between each other data[x +/- 1][y +/- 1] and get this picture

enter image description here

For the element on the border of the array, the neighbors are enter image description here

For an item in the corner

enter image description here

Total we have 1 general case when the element lies inside the array and 8 private ones (4 on the borders, 4 on the corners)

Of course, you can use the case-operator, go through these cases of searching for neighbors and solve this problem head-on, but are there more elegant solutions?

    2 answers 2

    How about, where in getElementsArr(i, j) i and j is the position of the central object:

     var arr = [ ["0:0","0:1","0:2","0:3"], ["1:0","1:1","1:2","1:3"], ["2:0","2:1","2:2","2:3"], ["3:0","3:1","3:2","3:3"] ]; function getElementsArr(i, j) { var yIndexes = getIndexes(arr, i); var xIndexes = getIndexes(arr[i], j); var thisArr = { topLeft: arr[yIndexes.prev][xIndexes.prev], top: arr[yIndexes.prev][xIndexes.curr], topRight: arr[yIndexes.prev][xIndexes.next], centerLeft: arr[yIndexes.curr][xIndexes.prev], center: arr[yIndexes.curr][xIndexes.curr], centerRight: arr[yIndexes.curr][xIndexes.next], bottomLeft: arr[yIndexes.next][xIndexes.prev], bottom: arr[yIndexes.next][xIndexes.curr], bottomRight: arr[yIndexes.next][xIndexes.next], } return thisArr; } function getIndexes(arr, i) { let prev = i - 1; let next = i + 1; if (i == 0) { prev = arr.length - 1; } else if (i == arr.length - 1) { next = 0; } return { prev: prev, curr: i, next: next }; } console.log(getElementsArr(0,0)); 

    Ps. Can only give more sonorous names to functions and variables ...

    • thank! interesting solution - while1pass

    There are only two boundary cases:

    1. when the value is greater than the maximum index
    2. when value is less than 0

    In order to process them you can use a simple formula:

     var index = (currIndex+count)%count; 

    Example:

     var size = 5; function* getRelative(rowIndex, colIndex) { for (var i = -1; i <= 1; i++) { for (var j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; yield { rowIndex: (rowIndex + i + size) % size, colIndex: (colIndex + j + size) % size } } } } $('td').click(function() { $('.relative,.active').removeClass('relative active'); var $this = $(this).addClass('active'); var colIndex = $this.index(); var rowIndex = $this.parent().index(); [...getRelative(rowIndex, colIndex)].forEach(coord => { $(`tr:nth-child(${coord.rowIndex+1}) td:nth-child(${coord.colIndex+1})`).addClass('relative'); }); }); 
     table { border-collapse: collapse; } td { border: 1px solid black; width: 50px; height: 50px; text-align: center; } .active { background-color: #add; } .active::after { content: '2'; } .relative { background-color: rgba(75, 255, 0, 0.59) } .relative::after { content: '1'; } 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <table> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> </table> 

    And further

     function* getRelative(rowIndex, colIndex, rowCount, colCount) { for (var i = -1; i <= 1; i++) { for (var j = -1; j <= 1; j++) { if (i == 0 && j == 0) continue; yield { rowIndex: (rowIndex + i + rowCount) % rowCount, colIndex: (colIndex + j + colCount) % colCount } } } } function clearCells() { var cells = document.querySelectorAll('.active, .relative'); for (var i = 0, len = cells.length; i < len; i++) { cells[i].classList.remove('active', 'relative') } } function createTable(rowCount, colCount) { return Array.from({ length: rowCount }, () => Array.from({ length: colCount })).reduce((table, cells, rowIndex) => { table.appendChild(cells.reduce((row, _, colIndex) => { var cell = document.createElement('td'); cell.addEventListener('click', function() { clearCells(); this.classList.add('active'); [...getRelative(rowIndex, colIndex, rowCount, colCount)].forEach(coord => { document.querySelector(`tr:nth-child(${coord.rowIndex+1}) td:nth-child(${coord.colIndex+1})`).classList.add('relative'); }); }) row.appendChild(cell); return row; }, document.createElement('tr'))) return table; }, document.createElement('table')) } document.body.appendChild(createTable(5, 10)); 
     table { border-collapse: collapse; } td { border: 1px solid black; width: 20px; height: 20px; text-align: center; } .active { background-color: #add; } .active::after { content: '2'; } .relative { background-color: rgba(75, 255, 0, 0.59) } .relative::after { content: '1'; } 

    • A very elegant solution through generators could supply two answers, both noted - while1pass
    • @ while1pass, what are the two answers? I seem to have one: calculating the correct index for each of the eight neighbors. Aaaaaaaaaaa :-D I misunderstood you so :-) - Grundy