【问题标题】:How to sort letters in a string?如何对字符串中的字母进行排序?
【发布时间】:2011-08-19 18:34:33
【问题描述】:

假设我有一个字符串s = "bcabca"

从中获取"aabbcc" 的最简单方法是什么,即对s 中的字母进行排序?

【问题讨论】:

  • 如何定义“最简单”?
  • 直截了当、自然、最短 :) 例如,在 Haskell 中,您可以说 sort "bcabca",然后得到“aabbcc”。这就是我所说的简单:)

标签: r sorting


【解决方案1】:

也许不是最简单的答案,但这会奏效:

paste(sort(unlist(strsplit(s, ""))), collapse = "")

或者修改?strsplit的帮助页面中定义的strReverse函数以满足我们的需要。我们称之为 strSort:

strSort <- function(x)
        sapply(lapply(strsplit(x, NULL), sort), paste, collapse="")

【讨论】:

  • 使用stri_flatten而不是paste的变体:stri_flatten(sort(unlist(strsplit(s,""))))
  • 当然,第一个答案在字符 vectors 上失败。我怀疑第二个会比sapply(strsplit(x, NULL), function(x) paste(sort(x), collapse = '') 慢(这已经很慢了)
【解决方案2】:

这是 Chase 解决方案的一个变体,它处理字符串向量并将原始字符串保留为名称。 ...我有机会推广使用 vapply 而不是 sapply :-)

> x=c('hello', 'world', NA, 'a whole sentence')
> vapply(x, function(xi) paste(sort(strsplit(xi, NULL)[[1]]), collapse=''), '')
             hello              world               <NA>   a whole sentence 
           "ehllo"            "dlorw"                 "" "  aceeeehlnnostw" 

【讨论】:

  • 是的,当你可以使用 vapply 时,永远不要使用 sapply!
  • 两年后再次阅读此内容,对此进行了非常轻微的修复以使其适用于矢量,请参阅我编辑的答案(只有在提交编辑后我才再次阅读您的回复并看到它只是一样!趋同进化...)
【解决方案3】:

重新审视这一点,我的旧答案不太好。这是带有base 函数的更好版本:

vapply(strsplit(x, NULL), function(x) paste(sort(x), collapse = ''), '')

基于这个测试向量:

NN = 1000000L
starts = seq(1L, NN, by = 100L)
name = 
  substring(paste(sample(letters, size = NN, replace = TRUE), collapse = ""),
            starts, starts + 99L)

【讨论】:

    【解决方案4】:

    对于这个问题,最好提及stringi 包。 stri_orderstri_sort 函数非常高效,测试时间是上述基本 R 方法的一半。

    library(stringi)
    ## generate 10k random strings of 100 characters each
    str <- stri_rand_strings(1e4, 100)
    ## helper function for vapply()
    striHelper <- function(x) stri_c(x[stri_order(x)], collapse = "")
    ## timings
    system.time({
      v1 <- vapply(stri_split_boundaries(str, type = "character"), striHelper, "")
    })
    #    user  system elapsed 
    #   0.747   0.000   0.743 
    
    system.time({
      v2 <- sapply(lapply(strsplit(str, NULL), sort), paste, collapse="")
    })
    #    user  system elapsed 
    #   2.077   0.000   2.068 
    
    identical(v1, v2)
    # [1] TRUE
    

    【讨论】:

    • stringi 通过 C 传递东西来加速吗?
    • @MichaelChirico - 是的,这个包几乎完全是用 C 编写的
    • 我会为 tidyverse 用户添加它 stringr::str_order 包装 stri_order 所以当你已经有 stringrtidyverse 加载时,你不需要显式加载另一个包。
    猜你喜欢
    • 2021-09-19
    • 2012-03-16
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 2017-10-04
    • 2013-02-09
    • 2019-03-21
    相关资源
    最近更新 更多