Since the question was originally with the r tag, then I provide a solution using R The logic of the solution is similar to the code in PHP.
find_ind_r <- function(x, value = 0L) { # Опередляем индексы idx <- which(x == value, arr.ind = TRUE) # Выделяем результирующий объект res <- list( row = rep(NA_integer_, nrow(x)), col = rep(NA_integer_, ncol(x)) ) # Счётчик count <- 1L # Считаем не повторяющиейся индексы for (i in seq_len(nrow(idx))) { r <- idx[i, ] if (!(r[1] %in% res$row) && !(r[2] %in% res$col)) { res$row[count] <- r[1] res$col[count] <- r[2] count <- count + 1L } } # Убираем незаполненные элементы length(res$row) <- count - 1L length(res$col) <- count - 1L return(res) }
If you intend to work with large arrays and require high performance, then it is better to implement an algorithm in C ++. The following is a solution using Rcpp .
test.cpp file:
#include <Rcpp.h> using namespace Rcpp; // [[Rcpp::export]] List find_ind_cpp(const NumericMatrix & x, double value) { std::size_t ncols = x.ncol(), nrows = x.nrow(); typedef std::unordered_set<std::size_t> ind_set; ind_set rows, cols; ind_set::iterator rows_end = rows.end(), cols_end = cols.end(); for (std::size_t i = 0; i < nrows; ++i) { for (std::size_t j = 0; j < ncols; ++j) { if (x[i + nrows * j] == value) { if (rows.find(i + 1) == rows_end && cols.find(j + 1) == cols_end) { rows.insert(i + 1); cols.insert(j + 1); } } } } List res = List::create(rows, cols); res.attr("names") = CharacterVector::create("rows", "cols"); return res; }
Executed in an R session or script:
x <- c(4,6,3,0,1,5,0, 0,0,4,3,3,1,12, 8,1,3,3,3,0,2, 0,0,10,5,3,5,12, 0,2,9,8,9,13,0, 0,15,0,1,2,6,10, 2,4,6,0,0,12,1) m <- matrix(x, nrow = 7, ncol = 7, byrow = TRUE) Rcpp::sourceCpp("/tmp/test.cpp") res <- find_ind_r(m, 0) paste(res$row, res$col, sep = "-", collapse = "; ") #> [1] "2-1; 4-2; 6-3; 1-4; 7-5; 3-6; 5-7"
Small benchmark:
set.seed(42) create_mat <- function(n) { matrix(sample(0:15, size = n * n, replace = TRUE), nrow = n, ncol = n) } res <- bench::press( n = c(10, 100, 1000), { mat <- create_mat(n) value <- 0 bench:::mark( min_iterations = 100, find_ind_cpp(mat, value), find_ind_r(mat, value), check = FALSE ) } ) plot(res)
