我已将for循环更改为sapply函数,但失败了 我想知道为什么?
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)
我选择音乐的规则是,如果基本名称(音乐)相同,则只保存一个full.name音乐,因此unique
不能直接使用。有两个概念full.name和文件路径中的basename可能会使人们感到困惑。
答案 0 :(得分:1)
你遇到的问题是你希望你的功能有两个副作用。副作用是指修改其范围之外的对象:w
和left
。
当然,w
和left
只在函数范围内被修改,然后它们最终会在函数调用结束时丢失。
相反,您希望在功能环境之外修改w
和left
。为此,您可以使用<<-
代替<-
:
sapply(z, function(y) {
if (is.element(basename(y),left)) {
w <<- append(w, values = y)
left <<- setdiff(left, basename(y))
}
})
请注意,我一直在说“你想要”,“你可以”,但这不是“你应该”做的。具有副作用的函数实际上被认为是错误的编程。试着阅读它。
此外,最好将*apply
工具保留给可以独立运行其输入的函数。相反,你有一个算法,迭代的结果取决于前一个的结果。在这些情况下,您最好使用for
循环,除非您可以在更适合*apply
的框架中重新考虑算法,或者可以使用可以处理此类依赖情况的函数:{{ 1}},filter
,unique
等
例如,使用rle
,您的代码可以重写为:
unique
它还有一个优点,就是它不会递归地构建一个对象,这是当前代码的另一个禁忌。