How to perform a check on a permutation “on-the-fly” without storing the result in R

不羁的心 提交于 2020-02-05 06:18:29

问题


Assume we have the following permutations of the letters, "a", "b", and "c":

library(combinat)
do.call(rbind, permn(letters[1:3]))
#      [,1] [,2] [,3]
# [1,] "a"  "b"  "c" 
# [2,] "a"  "c"  "b" 
# [3,] "c"  "a"  "b" 
# [4,] "c"  "b"  "a" 
# [5,] "b"  "c"  "a" 
# [6,] "b"  "a"  "c" 

Is it possible to perform some function on a given permutation "on-the-fly" (i.e., a particular row) without storing the result?

That is, if the row == "a" "c" "b" or row == "b" "c" "a", do not store the result. The desired result in this case would be:

#      [,1] [,2] [,3]
# [1,] "a"  "b"  "c" 
# [2,] "c"  "a"  "b" 
# [3,] "c"  "b"  "a" 
# [4,] "b"  "a"  "c" 

I know I can apply a function to all the permutations on the fly within combinat::permn with the fun argument such as:

permn(letters[1:3], fun = function(x) {
  res <- paste0(x, collapse = "")
  if (res == "acb" | res == "bca") {
    return(NA)
  } else {
    return(res)
  }
})

But this stills stores an NA and the returned list has 6 elements instead of the desired 4 elements:

# [[1]]
# [1] "abc"
# 
# [[2]]
# [1] NA
# 
# [[3]]
# [1] "cab"
# 
# [[4]]
# [1] "cba"
# 
# [[5]]
# [1] NA
# 
# [[6]]
# [1] "bac"

Note, I am not interested in subsequently removing the NA values; I am specifically interested in not appending to the result list "on-the-fly" for a given permutation.


回答1:


We could use a magrittr pipeline where we rbind the input matrix to the Rows to be checked and omit the duplicate rows.

library(combinat)
library(magrittr)

Rows <- rbind(c("a", "c", "b"), c("b", "c", "a"))

do.call(rbind, permn(letters[1:3])) %>% 
  subset(tail(!duplicated(rbind(Rows, .)), -nrow(Rows)))

giving:

     [,1] [,2] [,3]
[1,] "a"  "b"  "c" 
[2,] "c"  "a"  "b" 
[3,] "c"  "b"  "a" 
[4,] "b"  "a"  "c" 



回答2:


You can return NULL for the particular condition that you want to ignore and rbind the result which will ignore the NULL elements and bind only the combinations that you need.

do.call(rbind, combinat::permn(letters[1:3], function(x) 
   if(!all(x == c("a", "c", "b") | x == c("b", "c", "a")))
   return(x)
))

#    [,1] [,2] [,3]
#[1,] "a"  "b"  "c" 
#[2,] "c"  "a"  "b" 
#[3,] "c"  "b"  "a" 
#[4,] "b"  "a"  "c" 

Similarly,

do.call(rbind, permn(letters[1:3],function(x) { 
   res <- paste0(x, collapse = "")
  if (!res %in% c("acb","bca")) 
    return(res) 
}))

#      [,1] 
#[1,] "abc"
#[2,] "cab"
#[3,] "cba"
#[4,] "bac"


来源:https://stackoverflow.com/questions/59762657/how-to-perform-a-check-on-a-permutation-on-the-fly-without-storing-the-result

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!