【问题标题】:Reverse digits in RR中的反转数字
【发布时间】:2010-09-21 18:59:28
【问题描述】:

如何在 R 中反转一串数字?

例如,我有一个大约 1000 个六位数字的向量,我想知道它们是否是回文。我想创建一个完全相反的第二组,所以我可以进行对决。

【问题讨论】:

  • 您使用什么语言?
  • 如果除了回文没有重复,你可以试试:length(x) - length(unique(x))

标签: r reverse palindrome


【解决方案1】:

它实际上是您要测试为回文的数字的十进制表示,而不是数字本身(255 是十六进制和二进制的回文,但不是十进制)。

您可以使用模式匹配相当简单地做到这一点:

> tmp <- c(100001, 123321, 123456)
> grepl( '^([0-9])([0-9])([0-9])\\3\\2\\1$', tmp )
[1]  TRUE  TRUE FALSE
> 

您可以将数字转换为字符,拆分为单个字符 (strsplit),反转每个数字(sapply 和 rev),然后将值重新粘贴在一起(粘贴)并转换回数字(as.numeric)。但我认为,如果您只对 6 位数字键盘感兴趣,上述方法会更好。

【讨论】:

  • 很好的答案格雷格。我无法确定strsplit 或正则表达式方法是否更直接,但和您一样,我更喜欢正则表达式方法。这可能有助于解释为什么正则表达式有效。
  • 谢谢——这很好——我试过strsplit,太丑了
  • grepl 行中的帽子有什么作用——另外,双反斜杠有什么作用?
  • 帽子 (^) 匹配字符串的开头,美元符号 ($) 匹配结尾。这使得只有 6 位数字将匹配,而不是 7 或更大的部分。如果您知道所有数字最多为 6 位,那么两者都可以省略。
  • 反斜杠加倍,因为 R 字符串解析器将首先评估它们,这为正则表达式留下一个反斜杠,\1 表示匹配第一组括号匹配的内容,\2 表示匹配第二个匹配的是什么,等等。
【解决方案2】:

我不认为rev 完全做到了。它反转向量的元素,而问题是如何反转向量中的元素in

> nums <- sapply(1:10,function(i)as.numeric(paste(sample(1:9,6,TRUE),collapse="")))
> nums
 [1] 912516 568934 693275 835117 155656 378192 343266 685182 298574 666354
> sapply(strsplit(as.character(nums),""), function(i) paste(rev(i),collapse=""))
 [1] "615219" "439865" "572396" "711538" "656551" "291873" "662343" "281586" "475892" "453666"

【讨论】:

【解决方案3】:

编辑:我误读了这个问题。这是我给后代的答案。


你可以使用rev函数:

> 1:10
 [1]  1  2  3  4  5  6  7  8  9 10
> rev(1:10)
 [1] 10  9  8  7  6  5  4  3  2  1

【讨论】:

  • 你能把它应用到单个索引上吗?所以得到 1 2 3 等 8 9 01 11 21 31 41 等
  • 见乔希的回答; strsplit 函数通常用于分割子串。
【解决方案4】:

这应该适用于一般情况,可以选择任何基础:

is.palindromic <- function(x, base=10)
{
    p <- 0
    m <- floor(log(x,base))
    sig <- -1
    for (i in m:0)
        {
        tp <- floor(x/base^i)
        a <- i+1
        b <- m+1-i
        if(a==b){c<-0}else{c<-a*b;sig<-sig*-1}
        p <- p + tp*c*sig
        x <- x - tp*base^i
        }
    return(!as.logical(p))
}

【讨论】:

    【解决方案5】:

    stringi 包中有这个功能 - stri_reverse

    require(stringi)
    stri_reverse("123456")
    ## [1] "654321"
    

    现在回文函数可能就这么简单:

    palindrome <- function(x) stri_reverse(x)==x
    palindrome(c("651156","1234321"))
    ## [1] TRUE  TRUE
    

    【讨论】:

    • 我认为这是最好的答案。简短而简单,+1
    【解决方案6】:

    如果您对反转感兴趣,可以将 sub 与更长版本的 Greg 正则表达式一起使用:

    > x
    [1] 123321 343324 563660
    > sub( '^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])','\\6\\5\\4\\3\\2\\1', x)
    [1] "123321" "423343" "066365"
    

    虽然这比 split/rev/paste 快吗?

    【讨论】:

    • 是的,正则表达式比 split/rev/paste/as.numeric 更快(~5-10x)。
    【解决方案7】:

    使用intToUtf8进行拆分,然后反转:

    tmp <- c(100001, 123321, 123456)
    
    res <- sapply(tmp, function(i) intToUtf8(rev(utf8ToInt(as.character(i)))))
    
    res
    # [1] "100001" "123321" "654321"
    

    检查它是否是回文:

    tmp == res
    # [1]  TRUE  TRUE FALSE
    

    基准测试

    # bigger vector
    tmpBIG <- rep(c(100001, 123321, 123456), 4000)
    
    bench::mark(
      GregSnow = { grepl( '^([0-9])([0-9])([0-9])\\3\\2\\1$', tmpBIG) },
      bartektartanus = { tmpBIG == stringi::stri_reverse(tmpBIG) },
      Spacedman = { tmpBIG == sub( '^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])','\\6\\5\\4\\3\\2\\1', tmpBIG) },
      Joshua = { tmpBIG == sapply(strsplit(as.character(tmpBIG),""), function(i) paste(rev(i),collapse="")) },
      zx8754 = { tmpBIG == sapply(tmpBIG, function(i) intToUtf8(rev(utf8ToInt(as.character(i))))) },
      relative = TRUE)[, 1:9]
    
    # expression         min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
    # <bch:expr>       <dbl>  <dbl>     <dbl>     <dbl>    <dbl> <int> <dbl>   <bch:tm>
    # 1 GregSnow        1      1         6.82      1         NaN    23     0      517ms
    # 2 bartektartanus  1.38   1.34      5.02      2.33      NaN    17     0      520ms
    # 3 Spacedman       1.58   1.55      4.52      2.33      NaN    15     0      509ms
    # 4 Joshua          5.82   5.56      1.24      5.29      Inf     5     6      617ms
    # 5 zx8754          6.06   6.17      1         3.98      Inf     4     4      614ms
    

    【讨论】:

      猜你喜欢
      • 2020-05-14
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多