Comment concaténer deux chaînes?

375

Comment puis-je concaténer (fusionner, combiner) deux valeurs? Par exemple, j'ai:

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

Mon objectif est de concaténer les deux valeurs de "tmp" en une seule chaîne:

tmp_new = "GAD,AB"

Quelle fonction peut faire cela pour moi?

Hans
la source
La plupart des réponses ici se cassent si les chaînes sont des vecteurs, comme le notent les réponses de @ RichardScriven.
smci
@smci qu'en est-il de la petite réponse que j'ai postée? des suggestions pour l'améliorer?
joel.wilson

Réponses:

505
paste()

est la voie à suivre. Comme l'ont souligné les affiches précédentes, la pâte peut faire deux choses:

concaténer des valeurs en une "chaîne", par exemple

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

où l'argument sepspécifie le ou les caractères à utiliser entre les arguments pour concaténer ou réduire les vecteurs de caractères

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

où l'argument collapsespécifie le ou les caractères à utiliser entre les éléments du vecteur à réduire.

Vous pouvez même combiner les deux:

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

J'espère que cela t'aides.

Rainer
la source
9
Mélanger des chaînes et des vecteurs ou des vecteurs de différentes longueurs est un peu trop flexible à paste()mon goût. Par exemple, paste(c('a','b'),'blah', c(1,2,3))résulte en "a blah 1" "b blah 2" "a blah 3". Fondamentalement, il crée un vecteur de chaînes de la même longueur que le vecteur le plus long transmis et boucle les autres vecteurs / chaînes à la même longueur. Beaucoup de place pour un comportement accidentel là-bas.
naught101
1
Vrai - mais pouvez-vous proposer une approche alternative qui répond à la question?
Rainer
1
non - votre réponse est correcte (comme la plupart des autres réponses qui disent la même chose). Je viens de noter que le comportement de la pâte est inhabituel dans sa flexibilité.
naught101
2
@ naught101 Je ne considérerais pas cela comme inhabituel par rapport aux normes de R. Le recyclage des vecteurs est une propriété commune des fonctions R. Gardez à l' esprit que « bla » est un vecteur de longueur 1. La propriété de recyclage, il est facile de faire quelque chose comme paste0("blah", 1:3)obtenir "blah1" "blah2" "blah3".
Dason
5
Oui, je devrais me plaindre de R, pas seulement coller: P. Il est en fait incohérent dans R - data.frame()ne vous permet pas de le faire si les vecteurs ne sont pas multiples les uns des autres. matrix()crache des avertissements, mais array()ne le fait pas. Un peu ennuyeux. Vraiment, ils devraient tous cracher des avertissements à moins qu'une option ne soit définie ...
naught101
85

help.search() est une fonction pratique, par exemple

> help.search("concatenate")

vous mènera à paste().

rtelmore
la source
42

Pour la première non- paste()réponse, nous pouvons regarder stringr::str_c()(puis toString()ci-dessous). Cela n'existe pas depuis aussi longtemps que cette question, donc je pense qu'il est utile de mentionner qu'elle existe aussi.

Très simple à utiliser, comme vous pouvez le voir.

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

D'après sa description du fichier de documentation, il convient parfaitement à ce problème.

Pour comprendre comment str_c fonctionne, vous devez imaginer que vous construisez une matrice de chaînes. Chaque argument d'entrée forme une colonne et est étendu à la longueur de l'argument le plus long, en utilisant les règles de recylage habituelles. La chaîne sep est insérée entre chaque colonne. Si la réduction est NULL, chaque ligne est réduite en une seule chaîne. Si non NULL, cette chaîne est insérée à la fin de chaque ligne et la matrice entière est réduite à une seule chaîne.

Ajouté le 13/04/2016 : Ce n'est pas exactement la même chose que la sortie souhaitée (espace supplémentaire), mais personne ne l'a mentionné non plus. toString()est essentiellement une version paste()avec collapse = ", "codé en dur, vous pouvez donc faire

toString(tmp)
# [1] "GAD, AB"
Rich Scriven
la source
3
Hé, c'est la seule réponse qui traite du fait que tmp est un vecteur, et pas seulement un tas de valeurs - pastene fait pas de vecteurs. L'autre option est do.call(paste, as.list(tmp)).
naught101
35

Comme d'autres l'ont souligné, paste()c'est la voie à suivre. Mais il peut être ennuyeux d'avoir à taper à paste(str1, str2, str3, sep='')chaque fois que vous voulez le séparateur non par défaut.

Vous pouvez très facilement créer des fonctions wrapper qui vous simplifient la vie. Par exemple, si vous vous retrouvez à concaténer des chaînes sans séparateur très souvent, vous pouvez faire:

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

ou si vous voulez souvent joindre des chaînes à partir d'un vecteur (comme à implode()partir de PHP):

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

Vous permet de faire ceci:

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

De plus, il y a le intégré paste0, qui fait la même chose que le mien implode, mais sans autoriser les séparateurs personnalisés. C'est un peu plus efficace que paste().

rien101
la source
28

Alternativement, si votre objectif est de sortir directement vers un fichier ou une sortie standard, vous pouvez utiliser cat:

cat(s1, s2, sep=", ")
Megatron
la source
4
Alors à quoi bon poster une pasteréponse 4 ans plus tard alors qu'il y a déjà une dizaine de pasteréponses?
David Arenburg
4
À l'époque, j'ai trouvé utile de résumer plusieurs réponses par moi-même. L'objectif n'était pas de recueillir des votes mais d'aider les autres à filtrer les nombreuses solutions proposées. C'est souvent ce que je recherche.
Megatron
22

Autrement:

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

Il est parfois utile que la paste()fonction. %sindique l'endroit où les chaînes subjectives seront incluses.

Notez que cela vous sera utile lorsque vous essayez de créer un chemin:

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

production

/this/is/a/path
Suat Atan PhD
la source
pour les programmeurs C traitant de R, sprintf est familier et utile pour "concaténer deux chaînes"
subsci
Beaucoup mieux à mon humble avis. pasten'est pas assez flexible si vous voulez ajouter quelque chose à une chaîne.
displayname
20

Vous pouvez créer votre propre opérateur:

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

Vous pouvez également redéfinir les &opérateurs 'et' ( ):

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

jouer avec la syntaxe de base est moche, mais il en va de même paste()/paste0()si vous travaillez uniquement avec votre propre code, vous pouvez (presque toujours) remplacer l' & andopérateur logique par *et faire la multiplication des valeurs logiques au lieu d'utiliser les logiques 'et &'

Qbik
la source
@Richard Scriven peut-être que je ne comprends pas, mais cela semble simple, comparez: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))etas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik
très très bien! & est standard pour la concaténation dans de nombreuses langues, je pense en fait que R aurait dû l'avoir par défaut. recommande vivement cette façon
Serhii
14

Compte tenu de la matrice, tmp, que vous avez créée:

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

Je suppose qu'il y a une raison pour laquelle vous créez une matrice à l'aide de cbind, par opposition à simplement:

tmp <- "GAD,AB"
neilfws
la source
3

Considérez le cas où les chaînes sont des colonnes et le résultat doit être une nouvelle colonne:

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

Vous pouvez également ignorer le [c("a", "b")]sous-ensemble si toutes les colonnes doivent être collées.

# 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
la source
Ok mais les stringi, stringrbibliothèques sont plus rapides.
smci
2

Une autre réponse non collée:

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

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

glueest une nouvelle fonction, classe de données et package qui a été développé dans le cadre de la tidyverse, avec de nombreuses fonctionnalités étendues. Il combine les fonctionnalités de paste, sprintf et les autres réponses précédentes.

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

Créé le 2019-03-06 par le package reprex (v0.2.1)

Oui, c'est exagéré pour l'exemple simple de cette question, mais puissant pour de nombreuses situations. (voir https://glue.tidyverse.org/ )

Exemple rapide par rapport à pasteavec withci - dessous. Le gluecode était un peu plus facile à taper et semble un peu plus facile à lire.

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

Créé le 2019-03-06 par le package reprex (v0.2.1)

Arthur Yip
la source