¿Cómo se pueden concatenar dos cadenas?

375

¿Cómo puedo concatenar (fusionar, combinar) dos valores? Por ejemplo tengo:

tmp = cbind("GAD", "AB")
tmp
#      [,1]  [,2]
# [1,] "GAD" "AB"

Mi objetivo es concatenar los dos valores en "tmp" en una cadena:

tmp_new = "GAD,AB"

¿Qué función puede hacer esto por mí?

Hans
fuente
La mayoría de las respuestas aquí se rompen si las cadenas son vectores, como señala la respuesta de @ RichardScriven.
smci
@smci ¿qué pasa con la pequeña respuesta que he publicado? ¿Alguna sugerencia para mejorarlo?
joel.wilson el

Respuestas:

505
paste()

es el camino a seguir Como señalaron los carteles anteriores, pegar puede hacer dos cosas:

concatenar valores en una "cadena", por ejemplo

> paste("Hello", "world", sep=" ")
[1] "Hello world"

donde el argumento sepespecifica los caracteres que se utilizarán entre los argumentos para concatenar o contraer vectores de caracteres

> x <- c("Hello", "World")
> x
[1] "Hello" "World"
> paste(x, collapse="--")
[1] "Hello--World"

donde el argumento collapseespecifica los caracteres que se utilizarán entre los elementos del vector que se contraerá.

Incluso puedes combinar ambos:

> paste(x, "and some more", sep="|-|", collapse="--")
[1] "Hello|-|and some more--World|-|and some more"

Espero que esto ayude.

Rainer
fuente
99
Mezclar cadenas y vectores o vectores de diferentes longitudes es demasiado flexible paste()para mi gusto. Por ejemplo, paste(c('a','b'),'blah', c(1,2,3))resultados en "a blah 1" "b blah 2" "a blah 3". Básicamente, crea un vector de cadenas de la misma longitud que el vector más largo que se pasa y enlaza los otros vectores / cadenas a la misma longitud. Mucho espacio para el comportamiento accidental allí.
naught101
1
Es cierto, pero ¿puede proporcionar un enfoque alternativo que aborde la pregunta?
Rainer
1
no, su respuesta es correcta (como lo son la mayoría de las otras respuestas que dicen lo mismo). Solo noté que el comportamiento de la pasta es inusual en su flexibilidad.
naught101
2
@ naught101 No lo consideraría inusual para los estándares de R. El reciclaje de vectores es una propiedad común de las funciones R. Tenga en cuenta que 'bla' es un vector de longitud 1. La propiedad de reciclaje facilita hacer algo como paste0("blah", 1:3)obtener "blah1" "blah2" "blah3".
Dason
55
Sí, debería quejarme de R, no solo pegar: P. En realidad, es inconsistente en R: data.frame()no te permite hacerlo si los vectores no son múltiplos entre sí. matrix()escupe advertencias, pero array()no lo hace. Un poco molesto. Realmente, todos deberían escupir advertencias a menos que se establezca alguna opción ...
nada101
85

help.search() es una función útil, p. ej.

> help.search("concatenate")

le llevará a paste().

rtelmore
fuente
42

Para la primera no paste()respuesta, podemos mirar stringr::str_c()(y luego a toString()continuación). No ha existido tanto tiempo como esta pregunta, así que creo que es útil mencionar que también existe.

Muy simple de usar, como puedes ver.

tmp <- cbind("GAD", "AB")
library(stringr)
str_c(tmp, collapse = ",")
# [1] "GAD,AB"

De la descripción de su archivo de documentación, encaja bien con este problema.

Para comprender cómo funciona str_c, debe imaginar que está creando una matriz de cadenas. Cada argumento de entrada forma una columna y se expande a la longitud del argumento más largo, utilizando las reglas de reciclaje habituales. La cadena sep se inserta entre cada columna. Si el colapso es NULL, cada fila se contrae en una sola cadena. Si no es NULL, esa cadena se inserta al final de cada fila, y toda la matriz se contrae en una sola cadena.

Agregado 13/04/2016 : No es exactamente lo mismo que su salida deseada (espacio extra), pero nadie lo ha mencionado tampoco. toString()es básicamente una versión paste()con collapse = ", "código rígido, por lo que puedes hacer

toString(tmp)
# [1] "GAD, AB"
Rich Scriven
fuente
3
Heh, esta es la única respuesta que aborda el hecho de que tmp es un vector, y no solo un conjunto de valores, pasteno hace vectores. La otra opción es do.call(paste, as.list(tmp)).
naught101
35

Como otros han señalado, paste()es el camino a seguir. Pero puede ser molesto tener que escribir paste(str1, str2, str3, sep='')cada vez que desee el separador no predeterminado.

Puede crear fácilmente funciones de envoltura que hacen la vida mucho más simple. Por ejemplo, si te encuentras concatenando cadenas sin separador muy a menudo, puedes hacer:

p <- function(..., sep='') {
    paste(..., sep=sep, collapse=sep)
}

o si a menudo quieres unir cadenas de un vector (como implode()de PHP):

implode <- function(..., sep='') {
     paste(..., collapse=sep)
}

Te permite hacer esto:

p('a', 'b', 'c')
#[1] "abc"
vec <- c('a', 'b', 'c')
implode(vec)
#[1] "abc"
implode(vec, sep=', ')
#[1] "a, b, c"

Además, está incorporado paste0, que hace lo mismo que mi implode, pero sin permitir separadores personalizados. Es un poco más eficiente que paste().

nada101
fuente
28

Alternativamente, si su objetivo es enviar directamente a un archivo o stdout, puede usar cat:

cat(s1, s2, sep=", ")
Megatron
fuente
44
Entonces, ¿qué sentido tiene publicar una pasterespuesta 4 años después cuando ya hay una docena de pasterespuestas?
David Arenburg el
44
En ese momento me pareció útil resumir múltiples respuestas para mí. El objetivo no era recabar votos, sino ayudar a otros a filtrar las muchas soluciones ofrecidas. A menudo eso es lo que estoy buscando.
Megatron
22

De otra manera:

sprintf("%s you can add other static strings here %s",string1,string2)

A veces es útil que la paste()función. %sdenota el lugar donde se incluirán las cadenas subjetivas.

Tenga en cuenta que esto será útil cuando intente crear una ruta:

sprintf("/%s", paste("this", "is", "a", "path", sep="/"))

salida

/this/is/a/path
Suat Atan PhD
fuente
Para los programadores de C que trabajan con R, sprintf es familiar y útil para "concatenar dos cadenas"
subsci
Mucho mejor en mi humilde opinión. pasteno es lo suficientemente flexible si desea agregar algo a una cadena.
mostrar
20

Puede crear su propio operador:

'%&%' <- function(x, y)paste0(x,y)
"new" %&% "operator"
[1] newoperator`

También puede redefinir el &operador 'y' ( ):

'&' <- function(x, y)paste0(x,y)
"dirty" & "trick"
"dirtytrick"

jugar con la sintaxis de línea de base es feo, pero también lo es usarlo paste()/paste0()si trabajas solo con tu propio código, puedes (casi siempre) reemplazar el & andoperador lógico con *y multiplicar los valores lógicos en lugar de usar 'y' lógico

Qbik
fuente
@Richard Scriven puede que no entiendo, pero parece sencillo, comparar: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))yas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik
¡muy muy bien! & es estándar para la concatenación en muchos idiomas, de hecho creo que R debería haberlo tenido por defecto. Lo recomiendo encarecidamente de esta manera
Serhii
14

Dada la matriz, tmp, que creaste:

paste(tmp[1,], collapse = ",")

Supongo que hay alguna razón por la que está creando una matriz usando cbind, en lugar de simplemente:

tmp <- "GAD,AB"
neilfws
fuente
3

Considere el caso donde las cadenas son columnas y el resultado debería ser una nueva columna:

df <- data.frame(a = letters[1:5], b = LETTERS[1:5], c = 1:5)

df$new_col <- do.call(paste, c(df[c("a", "b")], sep = ", ")) 
df
#  a b c new_col
#1 a A 1    a, A
#2 b B 2    b, B
#3 c C 3    c, C
#4 d D 4    d, D
#5 e E 5    e, E

Opcionalmente, omita el [c("a", "b")]subconjunto si es necesario pegar todas las columnas.

# you can also try str_c from stringr package as mentioned by other users too!
do.call(str_c, c(df[c("a", "b")], sep = ", ")) 
joel.wilson
fuente
Ok, pero las stringi, stringrbibliotecas son más rápidas.
smci
2

Otra respuesta sin pegar:

x <- capture.output(cat(data, sep = ","))
x
[1] "GAD,AB"

Dónde

 data <- c("GAD", "AB")
sindri_baldur
fuente
2

gluees una nueva función, clase de datos y paquete que se ha desarrollado como parte de tidyverse, con mucha funcionalidad extendida. Combina características de paste, sprintf y las otras respuestas anteriores.

tmp <- tibble::tibble(firststring = "GAD", secondstring = "AB")
(tmp_new <- glue::glue_data(tmp, "{firststring},{secondstring}"))
#> GAD,AB

Creado el 06/03/2019 por el paquete reprex (v0.2.1)

Sí, es excesivo para el ejemplo simple en esta pregunta, pero poderoso para muchas situaciones. (ver https://glue.tidyverse.org/ )

Ejemplo rápido en comparación pastecon a withcontinuación. El gluecódigo fue un poco más fácil de escribir y parece un poco más fácil de leer.

tmp <- tibble::tibble(firststring = c("GAD", "GAD2", "GAD3"), secondstring = c("AB1", "AB2", "AB3"))
(tmp_new <- glue::glue_data(tmp, "{firststring} and {secondstring} went to the park for a walk. {firststring} forgot his keys."))
#> GAD and AB1 went to the park for a walk. GAD forgot his keys.
#> GAD2 and AB2 went to the park for a walk. GAD2 forgot his keys.
#> GAD3 and AB3 went to the park for a walk. GAD3 forgot his keys.
(with(tmp, paste(firststring, "and", secondstring, "went to the park for a walk.", firststring, "forgot his keys.")))
#> [1] "GAD and AB1 went to the park for a walk. GAD forgot his keys."  
#> [2] "GAD2 and AB2 went to the park for a walk. GAD2 forgot his keys."
#> [3] "GAD3 and AB3 went to the park for a walk. GAD3 forgot his keys."

Creado el 06/03/2019 por el paquete reprex (v0.2.1)

Arthur Yip
fuente