showkey
showkey

Reputation: 300

How to change the loop structure into sapply function?

I had changed the for loop into sapply function ,but failed .
I want to know why ?

list.files("c:/",pattern="mp3$",recursive=TRUE,full.names=TRUE)->z    
c()->w   
left<-basename(z)    
for (i in 1:length(z)){    
if (is.element(basename(z[i]),left))    
{     
   append(w,values=z[i])->w;    
   setdiff(left,basename(z[i]))->left    
   }}   
print(w) 



list.files("c:/",pattern="mp3$",recursive=TRUE,full.names=TRUE)->z    
c()->w    
left<-basename(z)    
sapply(z,function(y){    
if (is.element(basename(y),left))    
{  append(w,values=y)->w;    
   setdiff(left,basename(y))->left    
   }})    
print(w)

my rule of selecting music is that if the basename(music) is the same ,then save only one full.name of music ,so unique can not be used directly.there are two concepts full.name and basename in file path which can confuse people here.

Upvotes: 3

Views: 127

Answers (1)

flodel
flodel

Reputation: 89067

The problem you have here is that you want your function to have two side-effects. By side-effect, I mean modify objects that are outside its scope:w and left.

Curently, w and left are only modified within the function's scope, then they are eventually lost as the function call ends.

Instead, you want to modify w and left outside the function's environment. For that you can use <<- instead of <-:

sapply(z, function(y) {    
  if (is.element(basename(y),left)) {
    w <<- append(w, values = y)    
    left <<- setdiff(left, basename(y))   
  }
})

Note that I have been saying "you want", "you can", but this is not what "you should" do. Functions with side-effects are really considered bad programming. Try reading about it.

Also, it is good to reserve the *apply tools to functions that can run their inputs independently. Here instead, you have an algorithm where the outcome of an iteration depends on the outcome of the previous ones. These are cases where you're better off using a for loop, unless you can rethink the algorithm in a framework that better suits *apply or can make use of functions that can handle such dependent situations: filter, unique, rle, etc.

For example, using unique, your code can be rewritten as:

base.names <- basename(z)
left <- unique(base.names)
w <- z[match(left, base.names)]

It also has the advantage that it is not building an object recursively, another no-no of your current code.

Upvotes: 1

Related Questions