Como duas seqüências de caracteres podem ser concatenadas?

375

Como concatenar (mesclar, combinar) dois valores? Por exemplo, eu tenho:

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

Meu objetivo é concatenar os dois valores em "tmp" em uma string:

tmp_new = "GAD,AB"

Qual função pode fazer isso por mim?

Hans
fonte
A maioria das respostas aqui são quebradas se as strings são vetores, como observa a resposta de @ RichardScriven.
smci
@smci e a pequena resposta que eu postei? alguma sugestão para melhorá-lo?
precisa saber é o seguinte

Respostas:

505
paste()

é o caminho a percorrer. Como os pôsteres anteriores apontaram, a pasta pode fazer duas coisas:

concatenar valores em uma "string", por exemplo

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

em que o argumento sepespecifica o (s) caractere (s) a ser usado entre os argumentos para concatenar ou recolher vetores de caracteres

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

onde o argumento collapseespecifica o (s) caractere (s) a ser usado entre os elementos do vetor a ser recolhido.

Você pode até combinar os dois:

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

Espero que isto ajude.

Rainer
fonte
9
Misturar strings e vetores ou vetores de diferentes comprimentos é um pouco flexível demais paste()para o meu gosto. Por exemplo, paste(c('a','b'),'blah', c(1,2,3))resulta em "a blah 1" "b blah 2" "a blah 3". Basicamente, ele cria um vetor de strings do mesmo comprimento que o vetor mais longo que é passado e faz um loop dos outros vetores / strings no mesmo comprimento. Muito espaço para comportamento acidental lá.
naught101
11
É verdade - mas você pode fornecer uma abordagem alternativa que resolva a questão?
Rainer
11
não - sua resposta está correta (assim como a maioria das outras respostas que dizem a mesma coisa). Eu estava apenas observando que o comportamento da pasta é incomum em sua flexibilidade.
precisa saber é o seguinte
2
@ naught101 Eu não consideraria incomum para os padrões de R. A reciclagem de vetores é uma propriedade comum das funções R. Lembre-se de que 'blá' é um vetor de comprimento 1. A propriedade de reciclagem facilita a execução de algo como paste0("blah", 1:3)obter "blah1" "blah2" "blah3".
Dason 18/07/2014
5
Sim, eu deveria estar reclamando de R, não apenas colando: P. Na verdade, é inconsistente no R - data.frame()não permite fazer isso se os vetores não forem múltiplos um do outro. matrix()cospe avisos, mas array()não. Meio chato. Realmente, todos eles devem cuspir avisos a menos que alguma opção é definida ...
naught101
85

help.search() é uma função útil, por exemplo

> help.search("concatenate")

levará você a paste().

rtelmore
fonte
42

Para a primeira não paste()resposta, podemos olhar stringr::str_c()(e depoistoString() abaixo). Não existe há tanto tempo quanto essa pergunta, então acho útil mencionar que ela também existe.

Muito simples de usar, como você pode ver.

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

A partir da descrição do arquivo de documentação, ele se encaixa muito bem nesse problema.

Para entender como o str_c funciona, você precisa imaginar que está construindo uma matriz de strings. Cada argumento de entrada forma uma coluna e é expandido para o comprimento do argumento mais longo, usando as regras usuais de reciclagem. A sequência sep é inserida entre cada coluna. Se o recolhimento for NULL, cada linha será recolhida em uma única sequência. Se não NULL, essa sequência será inserida no final de cada linha e a matriz inteira será recolhida em uma única sequência.

Adicionado em 13/04/2016 : não é exatamente o mesmo que o resultado desejado (espaço extra), mas ninguém o mencionou. toString()é basicamente uma versão paste()com collapse = ", "hard-coded, para que possa fazer

toString(tmp)
# [1] "GAD, AB"
Rich Scriven
fonte
3
Heh, esta é a única resposta que aborda o fato de que tmp é um vetor, e não apenas um monte de valores - pastenão gera vetores. A outra opção é do.call(paste, as.list(tmp)).
precisa saber é o seguinte
35

Como outros já apontaram, paste()é o caminho a percorrer. Mas pode ser chato ter que digitar paste(str1, str2, str3, sep='')toda vez que você quiser o separador não padrão.

É muito fácil criar funções de invólucro que tornam a vida muito mais simples. Por exemplo, se você encontrar concatenações de strings sem separador com muita frequência, poderá:

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

ou se você frequentemente deseja juntar strings de um vetor (como implode()no PHP):

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

Permite que você faça isso:

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

Além disso, há o built-in paste0 , que faz o mesmo que o meu implode, mas sem permitir separadores personalizados. É um pouco mais eficiente que paste().

naught101
fonte
28

Como alternativa, se seu objetivo é gerar diretamente para um arquivo ou stdout, você pode usar cat:

cat(s1, s2, sep=", ")
Megatron
fonte
4
Então, qual o sentido de postar uma pasteresposta 4 anos depois, quando já existem cerca de uma dúzia de pasterespostas?
David Arenburg
4
Na época, achei útil resumir várias respostas para mim. O objetivo não era coletar votos, mas ajudar outras pessoas a filtrar as muitas soluções oferecidas. Muitas vezes é isso que estou procurando.
Megatron
22

Outra maneira:

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

Às vezes é útil que a paste()função. %sindica o local onde as cadeias subjetivas serão incluídas.

Observe que isso será útil quando você tentar criar um caminho:

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

resultado

/this/is/a/path
Suat Atan PhD
fonte
para programadores C lidar com R, sprintf é familiar e útil para "concatenar duas strings"
subsci
Muito melhor imho. pastenão é flexível o suficiente se você deseja acrescentar algo a uma string.
displayname
20

Você pode criar seu próprio operador:

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

Você também pode redefinir o &operador 'e' ( ):

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

mexer com a sintaxe da linha de base é feio, mas, paste()/paste0()se você trabalha apenas com seu próprio código, pode (quase sempre) substituir o & andoperador lógico por *e fazer a multiplicação dos valores lógicos em vez de usar o lógico 'e'

Qbik
fonte
@ Richard Scriven mayby Eu não entendo, mas parece simples, compare: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))eas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik
muito muito bom! & é padrão para concatenação em muitos idiomas, acho que R deveria tê-lo por padrão. recomendo vivamente esta maneira #
287 Serhii
14

Dada a matriz, tmp, que você criou:

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

Suponho que há alguma razão pela qual você está criando uma matriz usando cbind, em vez de simplesmente:

tmp <- "GAD,AB"
neilfws
fonte
3

Considere o caso em que as strings são colunas e o resultado deve ser uma nova coluna:

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, pule o [c("a", "b")]subconjunto se todas as colunas precisarem ser coladas.

# 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
fonte
Ok, mas as stringi, stringrbibliotecas são mais rápidas.
SMCI
2

Outra resposta não colada:

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

Onde

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

glueé uma nova função, classe de dados e pacote que foi desenvolvida como parte do tidyverse, com muitas funcionalidades estendidas. Ele combina recursos de colar, sprintf e as outras respostas anteriores.

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

Criado em 2019-03-06 pelo pacote reprex (v0.2.1)

Sim, é um exagero para o exemplo simples desta pergunta, mas poderoso para muitas situações. (veja https://glue.tidyverse.org/ )

Exemplo rápido em comparação pastecom o withabaixo. O gluecódigo foi um pouco mais fácil de digitar e parece um pouco mais fácil de ler.

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."

Criado em 2019-03-06 pelo pacote reprex (v0.2.1)

Arthur Yip
fonte