如何在不使用eval的情况下计算“1 + 1”(解析(...?

时间:2017-07-26 08:22:12

标签: r eval

我一直在寻找相当长一段时间,但似乎答案似乎总是使用eval(parse(text="1+1"))

我的数据框中有一列,它有一个字符串列表,例如“1 + 1 * 6”,“1 * 4/3”等。我希望在不使用{的情况下将这些列计算到新列中{1}}我正在寻找超过800万行的功能。

基本上是尝试回答这个问题:给定数字eval(parse(找到1:9所有的解决方案,其中(A_B_C) / (D_E_F) = GHI是数字A:I(不重复)下划线是四个运算符之一1:9,也没有重复。

我创建了一个包含*, /, +,-所有排列的数据框,并且对于每个排列,我计算了四个运算符的排列。

1:9

然而,这需要太长时间,因此我试图删除耗时的require(gtools) x <- permutations(n = 9, r = 9, v = 1:9) y <- permutations(n = 4, r = 4, v = c("*", "/", "+", "-")) for(i in 1:nrow(x)){ for(j in 1:nrow(y)){ math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")") equals <- eval(parse(text=math)) sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9])) if(sum==equals) { print(c(i,j)) } } }

任何帮助都会非常感激。谢谢!

房地

1 个答案:

答案 0 :(得分:1)

矢量化是关键

math <- apply(
  y,
  1,
  function(j){
    paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")")
  }
)
math <- apply(math, 2, paste, collapse = ",")
math <- paste("c(", math, ")")
equals <- sapply(parse(text = math), eval)
sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y))
abs(sum - equals) < 1e-8

让我们看看速度的差异是什么

需要(gtools)     x < - 置换(n = 9,r = 9,v = 1:9)     y&lt; - 排列(n = 4,r = 4,v = c(&#34; *&#34;,&#34; /&#34;,&#34; +&#34;,&# 34; - &#34))

x <- x[sample(nrow(x), 40), ]
y <- y[sample(nrow(y), 20), ]

library(microbenchmark)
microbenchmark(
  loop = for(i in 1:nrow(x)){
    for(j in 1:nrow(y)){
      math <- paste("(", x[i,1], y[j,1], x[i,2],y[j,2], x[i,3],")", "/", "(", x[i,4] ,y[j,3], x[i,5] ,y[j,4], x[i,6],")")
      equals <- eval(parse(text=math))
      sum <- as.numeric(paste0(x[i,7], x[i,8], x[i,9]))
      if(sum==equals) {
         print(c(i,j))
      }
    }
  },
  vectorised = {
    math <- apply(
      y,
      1,
      function(j){
        paste("(", x[, 1], j[1], x[, 2], j[2], x[, 3],")/(", x[, 4], j[3], x[, 5], j[4], x[, 6], ")")
      }
    )
    math <- apply(math, 2, paste, collapse = ",")
    math <- paste("c(", math, ")")
    equals <- sapply(parse(text = math), eval)
    sum <-matrix(x[, 7] * 100 + x[, 8] * 10 + x[, 9], nrow = nrow(x), ncol = nrow(y))
    abs(sum - equals) < 1e-8
  }
)

结果:

Unit: milliseconds
       expr        min         lq       mean     median         uq       max neval cld
       loop 158.666383 162.084918 167.477490 165.880665 170.258076 240.43746   100   b
 vectorised   8.540623   8.966214   9.613615   9.142515   9.413117  17.88282   100  a