Come si possono concatenare due stringhe?


375

Come posso concatenare (unire, unire) due valori? Ad esempio ho:

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

Il mio obiettivo è concatenare i due valori in "tmp" in una stringa:

tmp_new = "GAD,AB"

Quale funzione può fare questo per me?


La maggior parte delle risposte qui si interrompe se le stringhe sono vettori, come osserva la risposta di @ RichardScriven.
smci,

@smci e la piccola risposta che ho pubblicato? qualche suggerimento per migliorarlo?
joel.wilson,

Risposte:


505
paste()

è la strada da percorrere. Come sottolineato dai precedenti poster, incollare può fare due cose:

concatenare i valori in una "stringa", ad es

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

dove l'argomento sepspecifica i caratteri da utilizzare tra gli argomenti per concatenare o comprimere i vettori di caratteri

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

dove l'argomento collapsespecifica i caratteri da utilizzare tra gli elementi del vettore da comprimere.

Puoi anche combinare entrambi:

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

Spero che sia di aiuto.


9
Mischiare stringhe e vettori o vettori di diverse lunghezze è un po 'troppo flessibile paste()per i miei gusti. Ad esempio, paste(c('a','b'),'blah', c(1,2,3))risulta in "a blah 1" "b blah 2" "a blah 3". Fondamentalmente, crea un vettore di stringhe della stessa lunghezza del vettore più lungo che è passato e avvolge gli altri vettori / stringhe alla stessa lunghezza. C'è molto spazio per comportamenti accidentali lì.
naught101

1
Vero - ma puoi fornire un approccio alternativo che affronti la domanda?
Rainer,

1
no - la tua risposta è corretta (come la maggior parte delle altre risposte che dicono la stessa cosa). Stavo solo notando che il comportamento di Paste è insolito nella sua flessibilità.
naught101

2
@ naught101 Non lo considero insolito per gli standard di R. Il riciclaggio dei vettori è una proprietà comune delle funzioni R. Tenete a mente che 'bla' è un vettore di lunghezza 1. La struttura di riciclaggio rende facile fare qualcosa di simile paste0("blah", 1:3)per ottenere "blah1" "blah2" "blah3".
Dason,

5
Sì, dovrei lamentarmi di R, non solo di incollare: P. In realtà è incoerente tra R - data.frame()non ti consente di farlo se i vettori non sono multipli l'uno dell'altro. matrix()sputa avvertimenti, ma array()non lo fa. Un po 'fastidioso. Davvero, dovrebbero tutti sputare avvertimenti a meno che non sia impostata qualche opzione ...
nought101

85

help.search() è una funzione utile, ad es

> help.search("concatenate")

ti condurrà a paste().


42

Per la prima non paste()risposta, possiamo guardare stringr::str_c()(e poi toString()sotto). Non è in circolazione da così tanto tempo, quindi penso che sia utile menzionare che esiste anche.

Molto semplice da usare, come puoi vedere.

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

Dalla sua descrizione del file di documentazione, si adatta perfettamente a questo problema.

Per capire come funziona str_c, devi immaginare che stai costruendo una matrice di stringhe. Ogni argomento di input forma una colonna ed è espanso per la lunghezza dell'argomento più lungo, usando le consuete regole di ricyling. La stringa sep viene inserita tra ogni colonna. Se la compressione è NULL, ogni riga viene compressa in una singola stringa. Se non NULL quella stringa viene inserita alla fine di ogni riga e l'intera matrice viene compressa in una singola stringa.

13/04/2016 aggiunto : Non è esattamente lo stesso dell'output desiderato (spazio extra), ma nessuno lo ha nemmeno menzionato. toString()è fondamentalmente una versione paste()con collapse = ", "hard-coded, quindi puoi farlo

toString(tmp)
# [1] "GAD, AB"

3
Heh, questa è l'unica risposta che affronta il fatto che tmp è un vettore, e non solo un mucchio di valori - pastenon fa vettori. L'altra opzione è do.call(paste, as.list(tmp)).
naught101

35

Come altri hanno sottolineato, paste()è la strada da percorrere. Ma può essere fastidioso dover digitare paste(str1, str2, str3, sep='')ogni volta che si desidera il separatore non predefinito.

Puoi facilmente creare funzioni wrapper che semplificano la vita. Ad esempio, se ti ritrovi a concatenare stringhe senza separatore molto spesso, puoi fare:

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

o se vuoi spesso unire stringhe da un vettore (come implode()da PHP):

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

Ti permette di fare questo:

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

Inoltre, c'è il built-in paste0, che fa la stessa cosa del mio implode, ma senza consentire separatori personalizzati. È leggermente più efficiente di paste().



28

In alternativa, se il tuo obiettivo è l'output diretto in un file o stdout, puoi utilizzare cat:

cat(s1, s2, sep=", ")

4
Che senso ha pubblicare una pasterisposta 4 anni dopo, quando ci sono già circa una dozzina di pasterisposte?
David Arenburg,

4
Al momento ho trovato utile riassumere più risposte per me stesso. L'obiettivo non era quello di raccogliere voti ma di aiutare gli altri a filtrare attraverso le molte soluzioni offerte. Spesso è quello che sto cercando.
Megatron

22

Un altro modo:

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

A volte è utile della paste()funzione. %sindica il luogo in cui verranno incluse le stringhe soggettive.

Nota che questo ti sarà utile mentre provi a costruire un percorso:

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

produzione

/this/is/a/path

per i programmatori C che si occupano di R, sprintf è familiare e utile per "concatenare due stringhe"
subsci,

Imho molto meglio. pastenon è abbastanza flessibile se si desidera aggiungere qualcosa a una stringa.
displayname

20

Puoi creare il tuo operatore:

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

Puoi anche ridefinire l' &operatore 'e' ( ):

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

pasticciare con la sintassi della linea di base è brutto, ma lo è anche paste()/paste0()se si lavora solo con il proprio codice è possibile (quasi sempre) sostituire l' & andoperatore logico con *e moltiplicare i valori logici invece di usare 'e &' logici


@Richard Scriven mayby ​​non capisco, ma sembra semplice, confronta: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))eas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik

molto molto bene! ed è standard per la concatenazione in molte lingue, penso che R avrebbe dovuto averlo di default. consiglio vivamente in questo modo
Serhii il

14

Data la matrice, tmp, che hai creato:

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

Suppongo che ci sia qualche ragione per cui stai creando una matrice usando cbind, al contrario di semplicemente:

tmp <- "GAD,AB"

3

Considera il caso in cui le stringhe sono colonne e il risultato dovrebbe essere una nuova colonna:

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

Facoltativamente, saltare il [c("a", "b")]sottoinsieme se è necessario incollare tutte le colonne.

# 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 = ", ")) 

Ok ma le stringi, stringrbiblioteche sono più veloci.
smci,

2

Un'altra risposta non incolla:

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

Dove

 data <- c("GAD", "AB")

2

glueè una nuova funzione, classe di dati e pacchetto che è stato sviluppato come parte di tidyverse, con molte funzionalità estese. Unisce le funzionalità di paste, sprintf e le altre precedenti risposte.

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

Creato il 06-03-2019 dal pacchetto reprex (v0.2.1)

Sì, è eccessivo per il semplice esempio in questa domanda, ma è potente per molte situazioni. (vedi https://glue.tidyverse.org/ )

Esempio veloce rispetto a pastecon withdi seguito. Il gluecodice era un po 'più facile da digitare e sembra un po' più facile da leggere.

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

Creato il 06-03-2019 dal pacchetto reprex (v0.2.1)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.