Получите доступ к именам индексов внутри FUN

Это работает для меня сегодня с FF 57:

function () {
    // JQuery, today, doesn't play well with adding SVG elements - tricks required
    $(selector_to_node_in_svg_doc).parent().prepend($(this).clone().text("Your"));
    $(selector_to_node_in_svg_doc).text("New").attr("x", "340").text("New")
        .attr('stroke', 'blue').attr("style", "text-decoration: line-through");
}

Делает:

146
задан Community 23 May 2017 в 12:02
поделиться

1 ответ

@ferdinand-kraft дал нам большой прием и затем говорит нам, что мы не должны использовать его, потому что это не документировано и из-за производительности наверху.

я не могу спорить очень с первой точкой, но я хотел бы отметить, что издержки должны редко быть беспокойством.

позволяют нам определить активные функции, таким образом, мы не должны называть сложное выражение parent.frame()$i[], но только .i(), Мы также создадим .n() для доступа к имени, которое должно работать и на [1 110] основа и на purrr functionals (и вероятно большинство других также).

.i <- function() parent.frame(2)$i[]
# looks for X OR .x to handle base and purrr functionals
.n <- function() {
  env <- parent.frame(2)
  names(c(env$X,env$.x))[env$i[]]
}

sapply(cars, function(x) paste(.n(), .i()))
#>     speed      dist 
#> "speed 1"  "dist 2"

Теперь позволяют нам сравнить простой функции, Которая вставляет объекты вектора к их индексу, с помощью разных подходов (это, операции могут, конечно, быть векторизованы с помощью paste(vec, seq_along(vec)), но это не точка здесь).

Мы определяем функцию сравнительного тестирования и выводящуюся на печать функцию и выводим результаты на печать ниже:

library(purrr)
library(ggplot2)
benchmark_fun <- function(n){
  vec <- sample(letters,n, replace = TRUE)
  mb <- microbenchmark::microbenchmark(unit="ms",
                                      lapply(vec, function(x)  paste(x, .i())),
                                      map(vec, function(x) paste(x, .i())),
                                      lapply(seq_along(vec), function(x)  paste(vec[[x]], x)),
                                      mapply(function(x,y) paste(x, y), vec, seq_along(vec), SIMPLIFY = FALSE),
                                      imap(vec, function(x,y)  paste(x, y)))
  cbind(summary(mb)[c("expr","mean")], n = n)
}

benchmark_plot <- function(data, title){
  ggplot(data, aes(n, mean, col = expr)) + 
    geom_line() +
    ylab("mean time in ms") +
    ggtitle(title) +
    theme(legend.position = "bottom",legend.direction = "vertical")
}

plot_data <- map_dfr(2^(0:15), benchmark_fun)
benchmark_plot(plot_data[plot_data$n <= 100,], "simplest call for low n")

benchmark_plot(plot_data,"simplest call for higher n")

<глоток>, Созданный 15.11.2019 reprex пакет (v0.3.0)

, отбрасывание в начале первой диаграммы является счастливой случайностью, проигнорируйте его.

Мы видим, что выбранный ответ действительно быстрее, и для достойного объема повторений наш .i(), решения действительно медленнее, издержки по сравнению с выбранным ответом являются приблизительно 3 раза издержками использования purrr::imap(), и сумма к приблизительно, 25 мс для 30k повторений, таким образом, я теряю приблизительно 1 мс на 1 000 повторений, 1 секунда на миллион. Это - маленькая стоимость для удобства, по-моему.

0
ответ дан 23 November 2019 в 22:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: