For 循环只返回 R 中的最后一个值

时间:2021-05-24 08:22:25

标签: r for-loop

我在 R 中构建了一个 for 循环。但它只返回最后一个值。例如

asd <- c(0)
for (i in c(1,5)) {
  asd <- HTML("<tr>
          <td> '+d[",i,"]+' </td>
          <td>' + d[",i+1,"] + '</td>
          <td>' + d[",i+2,"] + '</td>
          <td>' + d[",i+3,"] + '</td>
          </tr>")
}

输出

asd
<tr><td> '+d[ 5 ]+' </td><td>' + d[ 6 ] + '</td><td>' + d[ 7 ] + '</td><td>' + d[ 8 ] + '</td></tr>

预期输出

'<tr><td> '+d[ 1 ]+' </td><td>' + d[ 2 ] + '</td><td>' + d[ 3 ] + '</td><td>' + d[ 4 ] + '</td></tr>
<tr><td> '+d[ 5 ]+' </td><td>' + d[ 6 ] + '</td><td>' + d[ 7 ] + '</td><td>' + d[ 8 ] + '</td></tr>'

有没有办法达到预期的输出

2 个答案:

答案 0 :(得分:1)

这会生成您预期的输出。

asd <- purrr::map_chr(c(1L,5L), ~ {
  paste0("<tr>",
          purrr::map_chr(seq(.x,.x + 3,1), ~ {
            glue::glue("<td>' + d[{.x}] + '</td>")
          }) %>% str_c(collapse = "")
         ,
         "</tr>")
})
asd
[1] "<tr><td>' + d[1] + '</td><td>' + d[2] + '</td><td>' + d[3] + '</td><td>' + d[4] + '</td></tr>"
[2] "<tr><td>' + d[5] + '</td><td>' + d[6] + '</td><td>' + d[7] + '</td><td>' + d[8] + '</td></tr>"

当然可以有基于 for 循环的解决方案,但我认为如果您正在使用 R,那么学习使用 apply/map 函数是值得的。

答案 1 :(得分:1)

for 循环从根本上不太适合这项任务(尤其是在 R 中,但也更普遍)。

但首先,循环中的各个条目是错误的,因为您没有读取 d 的值;并不完全清楚您的代码实际上在做什么(您没有告诉我们 HTML 函数的来源;我假设它来自‘htmltools’)。

您可能想使用 paste0 来连接值,否则您会得到不必要的空格。因此,要生成 HTML 表格的单列,您可以使用

paste0('<td>', d[i], '</td>')

由于 paste0 是矢量化的,您可以使用相同的代码一次生成所有四列:

paste0('<td>', d[seq(i, i + 4)], '</td>')

这将创建一个包含四个字符串的向量。但是我们想要一个字符串。我们可以用 paste0 参数告诉 collapse 折叠四个元素;我们指定分隔符:

cols = paste0('<td>', d[seq(i, i + 4)], '</td>', collapse = '\n')

现在我们可以使用 HTML 从这里创建一个 HTML 行:

HTML('<tr>', cols, '</tr>')

好的,一行就完成了。现在我们需要为您的所有行执行此操作。但是在 R 中,你不会为此使用循环;相反,您将使用 *apply 函数。

而且您不能像以前那样只对数字进行迭代。这将导致每行重复重叠索引的输出:

<tr>
  <td>1</td> <td>2</td> <td>3</td> <td>4</td>
</tr>
<tr>
  <td>2</td> <td>3</td> <td>4</td> <td>5</td>
</tr>
…

……很确定这不是您想要的。相反,您希望将输入数据分成 4 组。以巧妙的方式执行此操作有点棘手,但函数 split 在这里可以帮助我们。

首先,我们沿 d 生成索引,但从 0 (0, 1, 2, 3, ...) 开始:

idx = seq_along(d) - 1L

接下来,我们使用整数除法 (%/%) 以 4 将这些索引转换为组标识符:

groups = idx %/% 4L

现在 groups 的值为 c(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, …)。换句话说:前 4 个元素是 0,接下来的 4 个元素是 1,依此类推。这允许我们将 d 中的数据拆分为连续的 4 个组,然后我们依次将上述操作应用于每个组:

rows = lapply(
    split(d, groups),
    function (x) {
        cols = paste0('<td>', x[1 : 4], '</td>', collapse = '\n')
        HTML('<tr>', cols, '</tr>')
    }
)

lapply 将给定的函数应用于您传递给它的列表中的每个元素(这里是组列表,split(d, groups)),并返回结果列表。

这为您提供了一个 HTML 元素列表。最后,我们可以使用 Reduce:

组合这些元素
html = Reduce(HTML, rows)