Reputation: 300
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
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