获取字符向量的字母顺序的第一个和最后一个字母

时间:2016-07-21 15:45:12

标签: r

我正在做R练习:

编写一个函数,将字符串拆分为字母并返回min&按字母顺序排列的最大字母数。

这是矢量:

cities <- c("New York", "Paris", "London", "Tokyo", "Rio de Janeiro", "Cape Town")

这是我写的代码:

first_and_last <- function(name){
  name <- gsub (" ", "", name)
  letters <- strsplit(name, split = "")
  c(first = min(letters), last = max(letters)) 
  }

然而,当我运行它时出错:

first_and_last(cities)
#Error in min(letters) (from #4) : invalid 'type' (list) of argument

请告诉我代码中缺少的内容?谢谢!

2 个答案:

答案 0 :(得分:3)

首先,你的功能几乎是正确的。我已经包含了vapply()个循环来执行min()max()函数元素,然后返回结果的数据框。正如@Zheyuan Li指出你也可以使用sapply()这是有效的,但我更喜欢在编写函数时避免使用sapply()(参见Why is `vapply` safer than `sapply`?),尽管两者都能得到答案: - )

return_first_and_last <- function(name) {
  name <- gsub (" ", "", name)
  name <- strsplit(name, split = "")

  first <- vapply(name, min, "")
  last  <- vapply(name, max, "")

  data.frame(
   first = first,
   last  = last
  )
}

return_first_and_last(cities)
#       first last
# 1     e    Y
# 2     a    s
# 3     d    o
# 4     k    y
# 5     a    R
# 6     a    w

一些注意事项:

  • 将您的功能称为动词是一种很好的做法,因此我建议&#39; return_first_and_last()&#39;
  • letters是R中的内置对象,即使在本地功能环境中,重新分配这些内容通常也是一个坏主意。我一直只是替换name,因为我们在功能之外并不需要这样做。
  • 看起来资本化至关重要,至少在Linux上如此。因此,如果我们有两个相同的字母但一个大写和一个小写,min()将返回小写版本,max()将返回大写版本(即您的函数返回minamaxY,即使还有小写y

答案 1 :(得分:1)

我假设你想要按元素操作,即对于cities的每个元素,按字母顺序提取第一个和最后一个字母。这就是你需要的:

first_and_last <- function(name){
  name <- gsub (" ", "", name)
  myName <- strsplit(name, split = "")
  result <- t(sapply(myName, range))  ## use function `range`
  rownames(result) <- name
  colnames(result) <- c("first", "last")
  return(result)
  }

first_and_last(cities)

#                first last
# New York       "e"   "Y" 
# Paris          "a"   "s" 
# London         "d"   "o" 
# Tokyo          "k"   "y" 
# Rio de Janeiro "a"   "R" 
# Cape Town      "a"   "w" 

我使用了函数range()。这将返回minmax。它是R function(x) c(min(x), max(x))的内置实现。

<强>后续

  

谢谢,问题解决了。我在R学习在线课程。在他们的解决方案中,他们使用了以下代码。如果可能,请解释一下,这行代码意味着什么。特别是,双括号部分&#34; [[1]]&#34;:letters <- strsplit(name, split = "")[[1]]

strsplit返回一个列表。试试吧:

strsplit("Bath", split = "")
#[[1]]
#[1] "B" "a" "t" "h"

如果要访问角色向量,则需要[[1]]

strsplit("Bath", split = "")[[1]]
#[1] "B" "a" "t" "h"

只有使用矢量,您才能min / max。例如:

min(strsplit("Bath",split=""))
#Error in min(strsplit("Bath", split = "")) : 
#  invalid 'type' (list) of argument

min(strsplit("Bath",split="")[[1]])
#[1] "a"

我相信您看到的在线示例只需要一个字符。如果你有一个矢量输入,如:

strsplit(c("Bath", "Bristol", "Cambridge"), split = "")
#[[1]]
#[1] "B" "a" "t" "h"

#[[2]]
#[1] "B" "r" "i" "s" "t" "o" "l"

#[[3]]
#[1] "C" "a" "m" "b" "r" "i" "d" "g" "e"

并且您希望为每个列表元素应用rangesapply将非常方便:

sapply(strsplit(c("Bath", "Bristol", "Cambridge"), split = ""), range)
#     [,1] [,2] [,3]
#[1,] "a"  "B"  "a" 
#[2,] "t"  "t"  "r" 

上面的我的功能first_and_last基于sapply。然而,为了很好的演示,我已经转换了结果并给出了行/列名称。

天哪,我刚才意识到你已经在[[]] 2天前问过Double Bracket [[]] within a Function了。那么你为什么还要我解释呢?