Вызов назначенной переменной, созданной в функции в R, в той же функции - PullRequest
0 голосов
/ 27 марта 2020

Я пишу функцию, чтобы решить головоломку судоку. Часть этой функции будет использоваться для разделения матрицы на три матрицы 9x3. Затем я выполню действия над каждым из них, прежде чем объединить матрицы в одну большую матрицу.

На этом этапе мне бы хотелось, чтобы эта часть моей функции выполняла три вещи:

  1. разбить матрицу на три матрицы
  2. назвать каждую созданную матрицу
  3. вызвать новые матрицы в той же функции

Однако я борюсь с шагом 3. У меня есть Я написал функцию, которая разделит матрицу на три, назову каждую новую матрицу и, если я добавлю строку envir = globalenv(), функция вернет мою матрицу, разделенную на три матрицы размером 9x3, каждая со своим индивидуальным именем идентификатора. Отлично!

Однако в следующей части функции я хотел бы вызвать новые матрицы, созданные с помощью шагов 1 и 2 функции. Я не буду знать имя матриц до запуска функции, так как я хотел бы, чтобы код мог использоваться для многих матриц независимо от их размера.

Есть ли способ вызова объектов, созданных с помощью оператора функция, в рамках основной функции, когда все, что я буду знать, это то, что имена объектов будут "mat_n", где n является целым числом.

Для ясности, вот упрощенная версия моего кода:

m <- matrix(sample(c(0:9), 81, replace = T), ncol = 9, nrow = 9)

matrix_split <- function(x){

  i <- 1:length(x[, 1])
  a <- 1:sum(i %% 3 == 0) # Will be used to name the temporary matrices
  b <- which(i %% 3 == 0) # Will be used to identify where to split main matrix


  for(n in a){  # This is to create a number of smaller matrices depending on the
                # number multiples of 3 that are present in the length of the object.

    nam <- paste("mat_", n, sep = "") # Each new matrix will be named and numbered
                                      # using the assign function below:

    assign(nam, x[, c((b[a[n]] - (sum(i %% 3 == 0) - 1)) : b[a[n]])])

    # Not a very elegant way of using the loop to split the matrix into blocks of
    # three. b[a[n]] returns either 3, 6 or 9, and (sum(i %% == 3) -1 ) = 2. So this
    # will return x[, c(1:3)], x[, c(4:6)] and x[, c(7:9)], when spliting the matrix
    # into three.

    }

}


matrix_split(m)

Я только прошу указать конкретное c решение для вызова объектов, созданных функцией assign, для использования в моей основной функции после того, как они были созданы. Это был бы полезный навык, и это пробел в моих знаниях программирования (который не очень обширен).

Это может быть не лучший способ разбить матрицу, и я знаю, что пакеты уже есть созданный, который решит головоломку судоку, но я хотел бы написать свой собственный, и нет лучшего способа обучения, чем сначала делать что-то плохо, а потом улучшать его.

1 Ответ

1 голос
/ 27 марта 2020

Как насчет использования ls и parent.frame?

mat_4 <- matrix(LETTERS[1:16],nrow=4)
test <- function(){
ls(parent.frame())[grep("mat_",ls(parent.frame()))]
}
test()
# [1] "mat_4"
get(test())
#      [,1] [,2] [,3] [,4]
# [1,] "A"  "E"  "I"  "M" 
# [2,] "B"  "F"  "J"  "N" 
# [3,] "C"  "G"  "K"  "O" 
# [4,] "D"  "H"  "L"  "P" 

Или, если вы хотите включить текущую среду и каждый уровень выше, есть sys.frame().

Редактировать

Чтобы обойти необходимость знать имена объектов, возможно, лучше сохранить результаты в элементах списка.

matrix_split <- function(x){
  i <- 1:length(x[, 1])
  a <- 1:sum(i %% 3 == 0) 
  b <- which(i %% 3 == 0)
  #initialize list
  result <- list()
  for(n in a){  
    # assign submatrix to element in the list
    result[[n]] <- x[, c((b[a[n]] - (sum(i %% 3 == 0) - 1)) : b[a[n]])]
    }
do.call(cbind,result)
}

matrix_split(m)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
 [1,]    6    4    2    9    1    2    8    0    4
 [2,]    8    5    5    8    6    1    3    7    8
 [3,]    4    7    1    8    3    6    6    0    6
 [4,]    3    0    5    0    6    3    2    3    9
 [5,]    0    9    7    7    0    1    5    3    2
 [6,]    0    8    8    9    9    8    4    9    8
 [7,]    6    0    2    9    9    2    4    8    9
 [8,]    6    9    6    4    8    1    2    1    1
 [9,]    8    4    6    8    5    0    9    5    9
...