Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 如何组织大R功能?_Function_R - Fatal编程技术网

Function 如何组织大R功能?

Function 如何组织大R功能?,function,r,Function,R,我正在写一个R函数,它变得相当大了。它允许多项选择,我是这样组织的: myfun <- function(y, type=c("aa", "bb", "cc", "dd" ... "zz")){ if (type == "aa") { do something - a lot of code here - .... } if (type == "bb") { do something - a lot of c

我正在写一个R函数,它变得相当大了。它允许多项选择,我是这样组织的:

myfun <- function(y, type=c("aa", "bb", "cc", "dd" ... "zz")){

   if (type == "aa") {
      do something
      - a lot of code here -
      ....
   }

   if (type == "bb") {
      do something
      - a lot of code here -
      ....
   }

   ....
}
等等。 此外,代码“do something”中还有一些if语句。
我正在寻找组织代码的最佳方法

这是一个关于程序设计的更一般的问题。没有明确的答案,但几乎可以肯定有一条比你目前所做的更好的路线

编写处理不同类型的函数是一个很好的方法。它的有效性取决于几件事——例如,有多少种不同的类型?它们是否相关,例如,它们中的一些是否可以由同一个函数处理,根据输入的不同,其行为会略有不同

您应该试着以模块化的方式思考代码。总的来说,你有一个大任务要做。你能把它分解成一系列较小的任务,并编写执行较小任务的函数吗?您能否以一种不会使函数(更难)编写的方式概括这些任务中的任何一项,但却能使它们具有更广泛的适用性

如果您能更详细地说明您的计划应该实现的目标,我们将能够为您提供更多帮助。

选项1 一个选项是使用
开关
,而不是使用多个
if
语句:

myfun <- function(y, type=c("aa", "bb", "cc", "dd" ... "zz")){
  switch(type, 
    "aa" = sub_fun_aa(y),
    "bb" = sub_fun_bb(y),
    "bb" = sub_fun_cc(y),
    "dd" = sub_fun_dd(y)
  )
}  
这样称呼它:

myfun <- function(y, type=c("aa", "bb", "cc", "dd" ... "zz")){

   if (type == "aa") result <- sub_fun_aa(y)
   if (type == "bb") result <- sub_fun_bb(y)
   if (type == "cc") result <- sub_fun_cc(y)
   if (type == "dd") result <- sub_fun_dd(y)
   ....
}
> generalMethod("stuff", "unsharpMask")
[1] "stuff - General sharpening - Unsharp mask"
> hiPass("mystuff")
[1] "mystuff - General sharpening - Hipass filter"

几乎没有理由不将代码重构为更小的函数。在这种情况下,除了重组,还有一个额外的优势:受过教育的函数用户如果知道自己的位置,可以立即调用子函数

如果这些函数有很多参数,一个解决方案(便于维护)是将它们分组到“myFunctionParameters”类列表中,但这取决于您的情况


如果代码在不同的子函数之间共享,只需将其插入到每个子函数中使用的另一个函数中,或者(如果可行的话)预先计算这些内容并将其直接传递到每个子函数中。

这更像是一个一般编程问题,而不是R问题。因此,您可以遵循代码质量的基本准则。有一些工具可以通过阅读代码生成代码质量报告,并为您提供如何改进的指导。一个这样的例子是.NET代码的宪兵。以下是一个典型的指南,它会出现在方法过长的报告中:


如果一段代码至少可重复使用两次,我通常会将其“功能化”。如果不是,您最初在
If
语句中使用代码块的方法似乎是合理的。请查看这些关于重构的SO问题:我正在编写一个函数,它将不同的过滤器应用于图像(不同的过滤器=不同的“类型”参数)。一些滤波器共享一些代码(即,“aa”和“bb”是两个高斯滤波器,仅对一行代码不同),而其他滤波器则完全不同。所以我不得不使用很多if语句,例如,
if(type==“aa”| type==“bb”){
做一些aa和bb共同的事情
if(type==“aa”){
做一些与aa相关的
}if(type==“bb”){
做一些与bb相关的事情
}if(type==“cc”| type==“dd”){…
@Tommaso这些额外的信息应该真正用于你的问题,而不是作为对具体答案的评论。我建议你把它放在你的问题上。这看起来更优雅,所以感谢你的提示。我在对Chris Taylor的评论中添加了更多细节。Andrie:S3建议不错,但是新用户(我把自己算在这群人中;-)可能不太明白如何用它来代替一堆
if
switch
操作。您能详细说明或澄清如何使用S3代码吗?也许这可以是一个单独的答案,因为它有点长。@Iterator@Tommasso根据您的问题,我用一大块新的解释编辑了我的问题使用
match.fun
谢谢你的回答,也许这最适合我的目的。我唯一不明白的是,为什么为每个子函数重新编写共享代码是一种不推荐的方法(假设如果一个子函数运行,另一个子函数不会运行)。可能是为了节省空间。想象一下共享代码中有一个小错误(或者是在最初实现几个月后才想到的改进):如果重复代码,您将不得不在多个地方编辑它。
sharpening <- function(x){
  paste(x, "General sharpening", sep=" - ")
}

unsharpMask <- function(x){
  y <- sharpening(x)
  #... Some specific stuff here...
  paste(y, "Unsharp mask", sep=" - ")
}

hiPass <- function(x) {
  y <- sharpening(x)
  #... Some specific stuff here...
  paste(y, "Hipass filter", sep=" - ")
}

generalMethod <- function(x, type=c(hiPass, unsharpMask, ...)){
  match.fun(type)(x)
}
> generalMethod("stuff", "unsharpMask")
[1] "stuff - General sharpening - Unsharp mask"
> hiPass("mystuff")
[1] "mystuff - General sharpening - Hipass filter"