Hum, désolé d’avoir une question RTFM, mais j’ai dû mal chercher...
C’est possible pour une fonction de modifier un de ses arguments ?!
Hum, désolé d’avoir une question RTFM, mais j’ai dû mal chercher...
C’est possible pour une fonction de modifier un de ses arguments ?!
Bonjour,
Je crois deviner ce que tu veux dire, mais pourrais-tu être un peu plus précis sur les contraintes que tu as pour écrire ta fonction, le type d'objet à modifier, etc.
Un petit exemple de test (au moins là où tu en es de tes recherches) serait un plus.
Eh bien, plus précisément... disons que j'ai ça :
Et je voudrais une fonction step2() qui ait la propriété suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 step <- function(X) { n <- dim(X)[1]; m <- dim(X)[2]; repeat { I <- sample(1:n,2); J <- sample(1:m,2); if(X[I,J][2,1]>0 & X[I,J][1,2]>0) { X[I,J][2,1] <- X[I,J][2,1]-1; X[I,J][1,1] <- X[I,J][1,1]+1; X[I,J][1,2] <- X[I,J][1,2]-1; X[I,J][2,2] <- X[I,J][2,2]+1; break; } } return(X); }
step2(X) a le même effet que X <- step(X).
(edit) mais enfin on s'en fiche, j’aurais pu tout simplement avoir bidule <- function(x) return(x+1); et demander une fonction bidule2() qui incrémente son argument.![]()
Malheureusement - pour autant que je sache - on est obligé de passer par un stockage temporaire de la variable en raison des indices (j'ai jamais trouvé comment utiliser assign() pour des éléments d'une matrice).
La solution est de passer le nom de l'objet (et éventuellement son environnement d'origine à la fonction :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
26
27
28
29
30
31
32
33
34
35
36
37
38 > a <- matrix(rep(0:3, 3), ncol=4) > a [,1] [,2] [,3] [,4] [1,] 0 3 2 1 [2,] 1 0 3 2 [3,] 2 1 0 3 > step2 <- function(x, env=parent.frame()) + { + ## print(env) + X <- get(x, envir=env) + ## print(X) + n <- dim(X)[1] + m <- dim(X)[2] + repeat + { + I <- sample(1:n, 2) + J <- sample(1:m, 2) + if(X[I, J][2, 1] > 0 & X[I, J][1, 2] > 0) + { + X[I, J][2, 1] <- X[I, J][2, 1] - 1 + X[I, J][1, 1] <- X[I, J][1, 1] + 1 + X[I, J][1, 2] <- X[I, J][1, 2] - 1 + X[I, J][2, 2] <- X[I, J][2, 2] + 1 + break + } + } + assign(x, X, envir=env) + } > step2("a") > a [,1] [,2] [,3] [,4] [1,] 0 3 2 1 [2,] 1 0 2 3 [3,] 2 1 1 2
Merci. Malheureusement je ne pense pas gagner en efficacité comme ça...
Effectivement tu ne gagnes ni en terme de mémoire ni en terme d'assignage de variable (lent).
Il y a une autre façon de procéder, un peu plus compliquée, qui est basée sur le fait que les objets dans un environnement peuvent être indexés avec $ :
Le principe est de construire une commande avec paste() (décommente la ligne print... pour un exemple) et de l'évaluer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 step2 <- function(x, env=parent.frame()) { X <- paste("env$", x, sep="") repeat { I <- sample(1:nrow(get(x, envir=env)), 2) J <- sample(1:ncol(get(x, envir=env)), 2) if(get(x, envir=env)[I, J][2, 1] > 0 & get(x, envir=env)[I, J][1, 2] > 0) { ## print(paste(X, "[I, J][2, 1] <- ", X, "[I, J][2, 1] - 1", sep="")) eval(parse(text=paste(X, "[I, J][2, 1] <- ", X, "[I, J][2, 1] - 1", sep=""))) eval(parse(text=paste(X, "[I, J][1, 1] <- ", X, "[I, J][1, 1] + 1", sep=""))) eval(parse(text=paste(X, "[I, J][1, 2] <- ", X, "[I, J][1, 2] - 1", sep=""))) eval(parse(text=paste(X, "[I, J][2, 2] <- ", X, "[I, J][2, 2] + 1", sep=""))) break } } }
Si tu travailles sur de grosses matrices et/ou que tu lances la routine un nombre élevé de fois, ça doit valoir le coup.
Partager