【问题标题】:How can you tell if a pipe operator is the last (or first) in a chain?您如何判断管道操作员是否是链中的最后一个(或第一个)?
【发布时间】:2014-08-16 18:13:03
【问题描述】:

我最近一直在玩创建自己的管道,使用 magittr 中很棒的 pipe_with() 函数。我正在寻找跟踪当前链中管道的数量(因此我的管道可以根据其在链中的位置而表现不同)。我想我已经从magrittr github 页面得到了这个例子的答案:

# Create your own pipe with side-effects. In this example 
# we create a pipe with a "logging" function that traces
# the left-hand sides of a chain. First, the logger:
lhs_trace <- local({
  count <- 0
  function(x) {
    count <<- count + 1
    cl <- match.call()
    cat(sprintf("%d: lhs = %s\n", count, deparse(cl[[2]])))
  }
})

# Then attach it to a new pipe
`%L>%` <- pipe_with(lhs_trace)

# Try it out.
1:10 %L>% sin %L>% cos %L>% abs

1: lhs = 1:10
2: lhs = 1:10 %L>% sin
3: lhs = 1:10 %L>% sin %L>% cos
 [1] 0.6663667 0.6143003 0.9900591 0.7270351 0.5744009 0.9612168 0.7918362 0.5492263 0.9162743 0.8556344

左边的数字是管道号。但是,当我再次运行相同的链时,数字不会在 1 处重新开始:

> 1:10 %L>% sin %L>% cos %L>% abs
4: lhs = 1:10
5: lhs = 1:10 %L>% sin
6: lhs = 1:10 %L>% sin %L>% cos
 [1] 0.6663667 0.6143003 0.9900591 0.7270351 0.5744009 0.9612168 0.7918362 0.5492263 0.9162743 0.8556344

这大概是因为第一次使用%L&gt;%创建的本地环境在执行链中最后一个%L&gt;%时没有被破坏。因此,为了知道管道在当前链中的位置(不仅仅是从会话中的第一个管道开始),需要有一种方法在链结束时将 count 变量设置回 0(或重置本地环境)。

有人对如何做到这一点有任何想法吗?

【问题讨论】:

    标签: r piping magrittr


    【解决方案1】:

    在当前的dev 分支中,由于复合运算符%&lt;&gt;%,我们正在使用一种新方法,其中最后一个管道必须知道它是最后一个。无论如何,这意味着管道通过本地值toplevel 相对较快地了解这一点,该值可以是 TRUE 或 FALSE。不知道有没有用。

    特别是因为pipe_with 因收到的兴趣非常有限而被“搁置”。因此它不是当前dev 分支的一部分。

    【讨论】:

    • 很高兴知道!我想我会更熟悉dev 分支,看看我能用它做什么。谢谢!
    • 是的,等我有时间的时候,dev 大概就是master,还有很多其他的会被移除。
    • 查看这个要点以获得另一个建议gist.github.com/smbache/86fe703fa46e39df33ea
    【解决方案2】:

    其实,只是想到了一种方法。只计算match.call中子串“%L>”的出现次数:

    > lhs_trace2 <- function(x) {
    +     cl <- match.call()
    +     counter <- gregexpr("%L>%", cl[[2]], fixed = TRUE)[[1]]
    +     if (counter[1] == -1) count <- 1 else count <- length(counter) + 1
    +     cat(sprintf("%d: lhs = %s\n", count, deparse(cl[[2]])))
    +   }
    > 
    > # Then attach it to a new pipe
    > `%L>%` <- pipe_with(lhs_trace2)
    > 
    > # Try it out.
    > 1:10 %L>% sin %L>% cos %L>% abs
    1: lhs = 1:10
    2: lhs = 1:10 %L>% sin
    3: lhs = 1:10 %L>% sin %L>% cos
     [1] 0.6663667 0.6143003 0.9900591 0.7270351 0.5744009 0.9612168 0.7918362 0.5492263 0.9162743 0.8556344
    

    然后再次运行:

    > 1:10 %L>% sin %L>% cos %L>% abs
    1: lhs = 1:10
    2: lhs = 1:10 %L>% sin
    3: lhs = 1:10 %L>% sin %L>% cos
     [1] 0.6663667 0.6143003 0.9900591 0.7270351 0.5744009 0.9612168 0.7918362 0.5492263 0.9162743 0.8556344
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2011-06-19
      • 2012-10-10
      相关资源
      最近更新 更多