在两个字母之间创建一个序列

时间:2018-11-26 08:01:28

标签: r character

我想在两个字母之间创建一个序列,比如[ "H":[ { "id": 2134, "name": "Happy Brithday", "artist": "Paul Anka", "isFaved": false, "code": "380dj0a" }, { "id": 38304, "name": "How can i stop loving you", "artist": "Savage Garden", "isFaved": false, "code": "kkdj0a" } ] ] "b"。所以输出是

"f"

对于数字,我们可以做到

"b" "c" "d" "e" "f"

有没有一种简便的方法可以对字母进行处理?

我经历了Generate a sequence of characters from 'A'-'Z' ,但这会产生所有字母,而不是特定字母之间的顺序。

我当前的解决方案是

2:6 #which gives output as 
[1] 2 3 4 5 6

这行得通,但是我很好奇是否有一种简单的方法可以执行此操作,或者是否可以在我错过的任何软件包中使用该功能?

注意:我不想要indx <- which(letters %in% c("b", "f")); letters[indx[1] : indx[2]] #[1] "b" "c" "d" "e" "f" ,因为我事先不知道2和6。可以在任何两个字母之间。

9 个答案:

答案 0 :(得分:26)

这将是另一个基本的R选项:

letters[(letters >= "b") & (letters <= "f")]
# [1] "b" "c" "d" "e" "f"

答案 1 :(得分:17)

您可以创建自己的函数:

`%:%` <- function(l, r) {
    intToUtf8(seq(utf8ToInt(l), utf8ToInt(r)), multiple = TRUE)
}

用法:

"b" %:% "f"
# [1] "b" "c" "d" "e" "f"

"f" %:% "b"
# [1] "f" "e" "d" "c" "b"

"A" %:% "D"
# [1] "A" "B" "C" "D"

答案 2 :(得分:12)

带有matchseqdo.call的另一个选项:

letters[do.call(seq, as.list(match(c("b","f"), letters)))]

给出:

[1] "b" "c" "d" "e" "f"

具有此功能,使其可以同时使用小写和大写字母:

char_seq <- function(lets) {
  switch(all(grepl("[[:upper:]]", lets)) + 1L,
         letters[do.call(seq, as.list(match(lets, letters)))],
         LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
}

此输出:

> char_seq(c("b","f"))
[1] "b" "c" "d" "e" "f"

> char_seq(c("B","F"))
[1] "B" "C" "D" "E" "F"

可以通过检查输入的正确性来扩展此功能:

char_seq <- function(lets) {
  g <- grepl("[[:upper:]]", lets)
  if(length(g) != 2) stop("Input is not of length 2")
  if(sum(g) == 1) stop("Input does not have all lower-case or all upper-case letters")
  switch(all(g) + 1L,
         letters[do.call(seq, as.list(match(lets, letters)))],
         LETTERS[do.call(seq, as.list(match(lets, LETTERS)))])
}

输入不正确时会导致正确的错误消息:

> char_seq(c("B"))
Error in char_seq(c("B")) : Input is not of length 2

> char_seq(c("b","F"))
Error in char_seq(c("b", "F")) : 
  Input does not have all lower-case or all upper-case letters

答案 3 :(得分:10)

使用UTF播放,类似:

intToUtf8(utf8ToInt("b"):utf8ToInt("f"), multiple = TRUE)
# [1] "b" "c" "d" "e" "f"

答案 4 :(得分:8)

也许可以使用字母的原始版本然后转换回字符来定义类似于":"的中缀函数

 `%c:%` <- function(x,y) { strsplit( rawToChar(as.raw(
     seq(as.numeric(charToRaw(x)), as.numeric(charToRaw(y))))), "" )[[1]]}
>  'a' %c:% 'g'
[1] "a" "b" "c" "d" "e" "f" "g"

我当然不是说这可以满足“一种简单的方法”的要求,甚至不确定它是否会更有效,但是它确实引入了一些可能有用的功能。

答案 5 :(得分:8)

为什么不呢?

letters[which(letters == 'b') : which(letters == 'f')]

答案 6 :(得分:6)

不知道这是一种皱纹,但这是一个eval(parse(...))解决方案

LETTERS[eval(parse(text = paste(which(LETTERS %in% c('B', 'F')), collapse = ':')))]
#[1] "B" "C" "D" "E" "F"

答案 7 :(得分:1)

第一件事:您的代码

which(letters %in% c("b", "f"))

是一种有效的但令人费解的写作方式

match(c('b', 'f'), letters)

(为什么“卷积”?因为%in%是特定用例的match的包装器,因此将数字索引显式转换为逻辑值,即{{1的逆运算) }}。

接下来,您当然可以使用结果,并通过which将其转换为范围,在这种情况下,这没有任何问题。但是R有一种惯用的方式来表达使用向量作为参数的函数调用概念:microservices

idx[1L] : idx[2L]

或者,等效地:

do.call(`:`, as.list(match(c('b', 'f'), letters)))

{purrr}允许我们执行以下操作而无需使用do.call(seq, as.list(match(c('b', 'f'), letters)))

as.list

最后,我们子集:

purrr::invoke(seq, match(c('b', 'f'), letters))

答案 8 :(得分:1)

您可以使用grepletters以及模式[b-f]

grep("[b-f]", letters, value = TRUE)
#[1] "b" "c" "d" "e" "f"

letters[grep("[b-f]", letters)]
#[1] "b" "c" "d" "e" "f"

letters[grepl("[b-f]", letters)]
#[1] "b" "c" "d" "e" "f"

对于递减的序列,您可以另外使用rev

rev(grep("[b-f]", letters, value = TRUE))
#[1] "f" "e" "d" "c" "b"

或使用match

letters[match("b", letters) : match("f", letters)]
#[1] "b" "c" "d" "e" "f"