如何使用purrr::cross3的.filter参数直接筛选指定位置的组合结果
解决方案
cross3()的.filter参数无法直接实现按位置筛选,因为该参数接收的过滤函数仅能拿到三个输入向量当前迭代的元素值,无法获取当前组合在最终结果中的位置索引。
方案1:保留原有逻辑优化可读性(更推荐)
你现有的写法本身已经符合tidyverse风格,仅需用magrittr::extract替代反引号包裹的[即可大幅提升代码可读性:
library(purrr) library(magrittr) a <- cross3(5:1, 1:25, 1:5) %>% extract(c(1, 45, 203))
这种方式性能和实现成本都是最优的,不需要额外计算过滤规则,适合大型工作流使用。
方案2:通过.filter参数实现的方法
如果你必须要把筛选逻辑合并到cross3调用中,可以基于笛卡尔积的固定排列规则,反推目标位置对应的元素取值规则,再构造过滤函数:
cross3的排列顺序满足:总长度 = n1n2n3(n1为第一个参数长度、n2为第二个参数长度、n3为第三个参数长度),位置i(从1开始计数)对应的三个元素索引计算规则如下:
- 第三个参数的索引:
(i-1) %% n3 + 1 - 第二个参数的索引:
((i-1) %/% n3) %% n2 + 1 - 第一个参数的索引:
(i-1) %/% (n2*n3) + 1
基于上述规则实现的过滤代码如下:
target_pos <- c(1, 45, 203) n1 <- length(5:1) n2 <- length(1:25) n3 <- length(1:5) a <- cross3( .x = 5:1, .y = 1:25, .z = 1:5, .filter = function(x, y, z) { # 计算当前组合对应的位置 pos <- (match(x, 5:1) - 1) * n2 * n3 + (y - 1) * n3 + match(z, 1:5) pos %in% target_pos } )
注意:该方式需要遍历全部组合并逐个计算位置,性能远低于方案1,仅当有特殊需求必须合并步骤时使用。
内容的提问来源于stack exchange,提问作者User800701
相关产品推荐
相关产品推荐

