为多个字段做&符号在ruby中不起作用

时间:2018-05-11 22:33:54

标签: ruby

在红宝石中,我可以做到

['Hi', 'Yo'].map(&:upcase)

但如果我想同时同时获得:upcase:downcase该怎么办?

无论

['Hi', 'Yo'].map(&[:upcase,:downcase])

,也不

['Hi', 'Yo'].map([&:upcase,&:downcase])

的工作。 :(

3 个答案:

答案 0 :(得分:4)

你在这里有什么:

['Hi', 'Yo'].map(&:upcase)

实际上是以下的简短版本:

['Hi', 'Yo'].map(&:upcase.to_proc)

以下是:

的变体
['Hi', 'Yo'].map(&->(s) { s.send(:upcase) })

或换句话说:

['Hi', 'Yo'].map { |s| s.upcase }

对于这种情况,&:x符号实际上是一种特殊情况的简写,仅适用于单数符号。您可以做的是定义一个大致如下的to_proc方法:

class Array
  def to_proc
    ->(i) { inject(i) { |v, m| v.send(m) } }
  end
end

该方法必须返回一个Proc对象,一个" lambda",这里使用Ruby -> (...) { ... }表示法定义。

然后你可以这样称呼它:

['Hi', 'Yo'].map(&[:upcase, :downcase, :to_sym].to_proc)
# => [:hi, :yo]

答案 1 :(得分:1)

pooly <- function (object, method = "smallsample") { call <- match.call() if (!is.mira(object)) stop("The object must have class 'mira'") m <- length(object$analyses) fa <- getfit(object, 1) if (m == 1) { warning("Number of multiple imputations m=1. No pooling done.") return(fa) } analyses <- getfit(object) if (class(fa)[1] == "lme" && !requireNamespace("nlme", quietly = TRUE)) stop("Package 'nlme' needed fo this function to work. Please install it.", call. = FALSE) if ((class(fa)[1] == "mer" || class(fa)[1] == "lmerMod" || inherits(fa, "merMod")) && !requireNamespace("lme4", quietly = TRUE)) stop("Package 'lme4' needed fo this function to work. Please install it.", call. = FALSE) mess <- try(coef(fa), silent = TRUE) if (inherits(mess, "try-error")) stop("Object has no coef() method.") mess <- try(vcov(fa), silent = TRUE) if (inherits(mess, "try-error")) stop("Object has no vcov() method.") if (class(fa)[1] == "mer" || class(fa)[1] == "lmerMod" || inherits(fa, "merMod")) { k <- length(lme4::fixef(fa)) names <- names(lme4::fixef(fa)) } else if (class(fa)[1] == "polr") { k <- length(coef(fa)) + length(fa$zeta) names <- c(names(coef(fa)), names(fa$zeta)) } # added this --------------------------------- else if (class(fa)[1] == "multinom") { k <- length(coef(fa)) names <- rownames(vcov(fa)) } # -------------------------------------------- else { k <- length(coef(fa)) names <- names(coef(fa)) } qhat <- matrix(NA, nrow = m, ncol = k, dimnames = list(seq_len(m), names)) u <- array(NA, dim = c(m, k, k), dimnames = list(seq_len(m), names, names)) for (i in seq_len(m)) { fit <- analyses[[i]] if (class(fit)[1] == "mer") { qhat[i, ] <- lme4::fixef(fit) ui <- as.matrix(vcov(fit)) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class mer, fixef(fit): ", ncol(qhat), ", as.matrix(vcov(fit)): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } else if (class(fit)[1] == "lmerMod" || inherits(fa, "merMod")) { qhat[i, ] <- lme4::fixef(fit) ui <- vcov(fit) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class lmerMod, fixed(fit): ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } else if (class(fit)[1] == "lme") { qhat[i, ] <- fit$coefficients$fixed ui <- vcov(fit) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class lme, fit$coefficients$fixef: ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } else if (class(fit)[1] == "polr") { qhat[i, ] <- c(coef(fit), fit$zeta) ui <- vcov(fit) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class polr, c(coef(fit, fit$zeta): ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } else if (class(fit)[1] == "survreg") { qhat[i, ] <- coef(fit) ui <- vcov(fit) parnames <- dimnames(ui)[[1]] select <- !(parnames %in% "Log(scale)") ui <- ui[select, select] if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class survreg, coef(fit): ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } # added this block ------------------------------------- else if (class(fit)[1] == "multinom") { qhat[i, ] <- c(t(coef(fit))) # transpose to get same order as standard errors ui <- vcov(fit) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: class multinom, c(coef(fit)): ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } # ---------------------------------------------------- else { qhat[i, ] <- coef(fit) ui <- vcov(fit) ui <- expandvcov(qhat[i, ], ui) if (ncol(ui) != ncol(qhat)) stop("Different number of parameters: coef(fit): ", ncol(qhat), ", vcov(fit): ", ncol(ui)) u[i, , ] <- array(ui, dim = c(1, dim(ui))) } } qbar <- apply(qhat, 2, mean) ubar <- apply(u, c(2, 3), mean) e <- qhat - matrix(qbar, nrow = m, ncol = k, byrow = TRUE) b <- (t(e) %*% e)/(m - 1) t <- ubar + (1 + 1/m) * b r <- (1 + 1/m) * diag(b/ubar) lambda <- (1 + 1/m) * diag(b/t) dfcom <- df.residual(object) df <- mice.df(m, lambda, dfcom, method) fmi <- (r + 2/(df + 3))/(r + 1) names(r) <- names(df) <- names(fmi) <- names(lambda) <- names fit <- list(call = call, call1 = object$call, call2 = object$call1, nmis = object$nmis, m = m, qhat = qhat, u = u, qbar = qbar, ubar = ubar, b = b, t = t, r = r, dfcom = dfcom, df = df, fmi = fmi, lambda = lambda) oldClass(fit) <- c("mipo", oldClass(object)) return(fit) } environment(pooly) <- environment(mice) 通过定义方法&:symbol来工作。

以下是原始Ruby中定义的Symbol#to_proc的示例:

http://maximomussini.com/posts/ruby-to_proc/

Symbol#to_proc

C版本添加了一个缓存,因此每次重新创建块都不会减慢我们的速度。

要获得您想要的内容,请定义class Symbol def to_proc ->(obj, args = nil) { obj.send(self, *args) } end end 并拥有它!

答案 2 :(得分:1)

符号#to_proc可用作调用一个方法的基本情况的简写。如果你想要更复杂的东西,只需转移到手写

['Hi', 'Yo'].map { |word| [word.upcase, word.downcase] }

将返回[['HI', 'hi'], ['YO', 'yo']] - 如果您想要的是flatten,则可以调用['HI', 'hi', 'YO', 'yo']

更新:因为你真的想要[['HI','YO'], ['hi', 'yo']],你可以在结果上调用转置

['Hi', 'Yo'].map { |w| [w.upcase, w.downcase] }.transpose

注意:以下是一个可怕的想法,没有人应该在实际代码中实现它,因为Array#to_proc的含义是完全不明显的(它是否调用all并返回一个数组,是否链接,是否通过方法的参数等),但既然你已经要求它,你可以做类似

的事情
class Array
   def to_proc
     lambda { |o| map { |m| o.send(m) } }
   end
end

允许

['Hi', 'Yo'].map(&[:upcase, :downcase]).transpose

产生你要求的答案。它确实保存了几个字符,但它不值得添加到代码中的歧义。