对象上的函数序列

时间:2017-04-15 17:13:19

标签: r

在R中,是否有推荐的方法将函数列表应用于对象,以便将第(n-1)函数的输出插入到第n个函数中?

例如,假设我有一个用于清理字符串的函数列表;我想将它们全部应用到同一个不干净的字符串中,例如:

mystring <- "ImPortant info - some extra";
cleaning_functions <- 
  list(function(s){tolower(s)}, 
       function(s){substr(s, 1, grep(' -') -1)})

最终结果是:"important info" 这可以通过循环实现;但我希望有一个“plyr”式的解决方案 如果碰巧循环是有效的,那么就是这样;但如果它是最佳的,我会感到惊讶。

请注意,对于我的最终解决方案,操作顺序很重要,所提供的功能列表将动态创建并可能未命名。

2 个答案:

答案 0 :(得分:3)

这称为function composition。皮肤猫的方法有很多种。最简单的方法是编写一个简单的包装器,或使用现有的库(参见例如链接):

compose = function (f, g) {
    function (...) f(g(...))
}

然后将其应用于您的问题:

cleaning_functions = do.call(compose, cleaning_functions)
# or, directly
cleaning_functions = compose(tolower, function (s) substr(s, 1, regexpr(' -', s) - 1))

并像任何函数一样调用它:

cleaning_functions(my_string)

答案 1 :(得分:1)

生成一些测试函数:

test1 <- function(x){paste(x,"a",sep="")}
test2 <- function(x){paste(x,"b",sep="")}
test3 <- function(x){paste(x,"c",sep="")}
test4 <- function(x){paste(x,"d",sep="")}
test5 <- function(x){paste(x,"e",sep="")}

然后调用这些函数:

string <- "test"
for (i in c("test1","test2","test3","test4","test5")) {
  string <- do.call(i, list(string))
}
string
[1] "testabcde"

对于您的具体示例,以下内容应该有效:

mystring <- "ImPortant info - some extra"
cleaning_functions <- 
   list(function(s){tolower(s)}, 
      function(s){substr(s, 1, regexpr(' -', s) - 1)})
for (i in cleaning_functions) {
   mystring <- do.call(i, list(mystring))
}
mystring
[1] "important info"

请注意,我必须将grep更改为regexpr才能生效。