Wie können zwei Zeichenfolgen verkettet werden?

375

Wie kann ich zwei Werte verketten (zusammenführen, kombinieren)? Zum Beispiel habe ich:

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

Mein Ziel ist es, die beiden Werte in "tmp" zu einer Zeichenfolge zu verketten:

tmp_new = "GAD,AB"

Welche Funktion kann das für mich tun?

Hans
quelle
Die meisten Antworten hier brechen, wenn die Zeichenfolgen Vektoren sind, wie die Antwortnotizen von @ RichardScriven zeigen.
smci
@smci was ist mit der kleinen Antwort, die ich gepostet habe? irgendwelche Vorschläge, um es zu verbessern?
joel.wilson

Antworten:

505
paste()

ist der Weg zu gehen. Wie die vorherigen Poster gezeigt haben, kann Paste zwei Dinge tun:

verketten Sie Werte zu einer "Zeichenfolge", z

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

Dabei gibt das Argument sepdie Zeichen an, die zwischen den Argumenten verwendet werden sollen, um Zeichenvektoren zu verketten oder zu reduzieren

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

Dabei gibt das Argument collapsedie Zeichen an, die zwischen den Elementen des zu reduzierenden Vektors verwendet werden sollen.

Sie können sogar beide kombinieren:

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

Hoffe das hilft.

Rainer
quelle
9
Das Mischen von Strings und Vektoren oder Vektoren unterschiedlicher Länge ist paste()für meinen Geschmack etwas zu flexibel . Zum Beispiel paste(c('a','b'),'blah', c(1,2,3))ergibt sich "a blah 1" "b blah 2" "a blah 3". Grundsätzlich wird ein Vektor von Zeichenfolgen mit der gleichen Länge wie der längste übergebene Vektor erstellt und die anderen Vektoren / Zeichenfolgen mit derselben Länge durchlaufen. Viel Platz für versehentliches Verhalten.
naught101
1
Stimmt - aber können Sie einen alternativen Ansatz anbieten, der die Frage beantwortet?
Rainer
1
nein - Ihre Antwort ist richtig (wie auch die meisten anderen Antworten, die dasselbe sagen). Ich habe nur bemerkt, dass das Verhalten der Paste in ihrer Flexibilität ungewöhnlich ist.
Naught101
2
@ naught101 Ich würde es nach Rs Maßstäben nicht als ungewöhnlich betrachten. Vektorrecycling ist eine gemeinsame Eigenschaft von R-Funktionen. Denken Sie daran, dass 'bla' ein Vektor der Länge 1 ist. Die Recycling-Eigenschaft macht es einfach, so etwas wie paste0("blah", 1:3)zu bekommen "blah1" "blah2" "blah3".
Dason
5
Ja, ich sollte mich über R beschweren, nicht nur einfügen: P. Es ist tatsächlich in R inkonsistent - data.frame()lässt Sie es nicht zu, wenn Vektoren kein Vielfaches voneinander sind. matrix()spuckt Warnungen aus, array()tut es aber nicht. Irgendwie nervig. Wirklich, sie sollten alle Warnungen ausspucken, es sei denn, eine Option ist festgelegt ...
naught101
85

help.search() ist eine praktische Funktion, z

> help.search("concatenate")

wird dich zu führen paste().

rtelmore
quelle
42

Für die erste Nichtantwort paste()können wir schauen stringr::str_c()(und danntoString() unten) . Es gab diese Frage noch nicht so lange, daher halte ich es für nützlich zu erwähnen, dass sie auch existiert.

Sehr einfach zu bedienen, wie Sie sehen können.

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

Aus der Beschreibung der Dokumentationsdatei geht hervor, dass es gut zu diesem Problem passt.

Um zu verstehen, wie str_c funktioniert, müssen Sie sich vorstellen, dass Sie eine Matrix von Zeichenfolgen aufbauen. Jedes Eingabeargument bildet eine Spalte und wird unter Verwendung der üblichen Recyling-Regeln auf die Länge des längsten Arguments erweitert. Die Sep-Zeichenfolge wird zwischen jede Spalte eingefügt. Wenn Collapse NULL ist, wird jede Zeile zu einer einzelnen Zeichenfolge reduziert. Wenn diese Zeichenfolge nicht NULL ist, wird sie am Ende jeder Zeile eingefügt und die gesamte Matrix wird zu einer einzelnen Zeichenfolge zusammengefasst.

Hinzugefügt am 13.04.2016 : Es ist nicht genau das Gleiche wie Ihre gewünschte Ausgabe (zusätzlicher Speicherplatz), aber niemand hat es auch erwähnt. toString()ist im Grunde eine Version von paste()mit collapse = ", "hartcodierten, so dass Sie tun können

toString(tmp)
# [1] "GAD, AB"
Rich Scriven
quelle
3
Heh, dies ist die einzige Antwort, die sich mit der Tatsache befasst, dass tmp ein Vektor ist und nicht nur eine Reihe von Werten - pastekeine Vektoren. Die andere Option ist do.call(paste, as.list(tmp)).
naught101
35

Wie andere betont haben, paste()ist der Weg zu gehen. Es kann jedoch ärgerlich werden, paste(str1, str2, str3, sep='')jedes Mal eingeben zu müssen, wenn Sie das nicht standardmäßige Trennzeichen verwenden möchten.

Sie können sehr einfach Wrapper-Funktionen erstellen, die das Leben viel einfacher machen. Wenn Sie beispielsweise häufig Zeichenfolgen ohne Trennzeichen verketten, können Sie Folgendes tun:

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

oder wenn Sie häufig Zeichenfolgen aus einem Vektor (wie implode()aus PHP) verbinden möchten :

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

Ermöglicht dies:

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

Es gibt auch das eingebaute System paste0, das das Gleiche wie ich tut implode, jedoch keine benutzerdefinierten Trennzeichen zulässt. Es ist etwas effizienter als paste().

naught101
quelle
28

Wenn Sie alternativ direkt in eine Datei oder eine Standardausgabe ausgeben möchten, können Sie alternativ Folgendes verwenden cat:

cat(s1, s2, sep=", ")
Megatron
quelle
4
Was bringt es also paste, 4 Jahre später eine Antwort zu veröffentlichen, wenn es bereits etwa ein Dutzend pasteAntworten gibt?
David Arenburg
4
Zu der Zeit fand ich es hilfreich, mehrere Antworten für mich zusammenzufassen. Ziel war es nicht, Stimmen zu sammeln, sondern anderen zu helfen, durch die vielen angebotenen Lösungen zu filtern. Oft ist es das, wonach ich suche.
Megatron
22

Ein anderer Weg:

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

Es ist manchmal nützlich als paste()Funktion. %sbezeichnet den Ort, an dem die subjektiven Zeichenfolgen enthalten sein werden.

Beachten Sie, dass dies nützlich sein wird, wenn Sie versuchen, einen Pfad zu erstellen:

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

Ausgabe

/this/is/a/path
Suat Atan PhD
quelle
Für C-Programmierer, die sich mit R befassen, ist Sprintf bekannt und nützlich, um "zwei Zeichenfolgen zu verketten"
Subsci
Viel besser imho. pasteist nicht flexibel genug, wenn Sie etwas an eine Zeichenfolge anhängen möchten.
Anzeigename
20

Sie können Ihren eigenen Operator erstellen:

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

Sie können den &Operator 'und' ( ) auch neu definieren :

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

Das Durcheinander mit der Basissyntax ist hässlich, aber paste()/paste0()wenn Sie nur mit Ihrem eigenen Code arbeiten, können Sie (fast immer) den logischen & andOperator durch *logische Werte ersetzen und diese multiplizieren, anstatt logisches 'und &' zu verwenden.

Qbik
quelle
@ Richard Scriven Mayby Ich verstehe nicht, aber es scheint unkompliziert, vergleiche: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))undas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik
sehr sehr gut! & ist Standard für die Verkettung in vielen Sprachen. Ich denke, R hätte es standardmäßig haben sollen. empfehlen diesen Weg
Serhii
14

Angesichts der von Ihnen erstellten Matrix tmp:

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

Ich nehme an, es gibt einen Grund, warum Sie eine Matrix mit cbind erstellen, im Gegensatz zu einfach:

tmp <- "GAD,AB"
neilfws
quelle
3

Stellen Sie sich den Fall vor, in dem die Zeichenfolgen Spalten sind und das Ergebnis eine neue Spalte sein sollte:

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

Überspringen [c("a", "b")]Sie optional die Teilmenge, wenn alle Spalten eingefügt werden müssen.

# 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
quelle
Ok, aber stringi, stringrBibliotheken sind schneller.
smci
2

Eine weitere Antwort ohne Einfügen:

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

Wo

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

glueist eine neue Funktion, Datenklasse und ein neues Paket, das als Teil von entwickelt wurde und tidyverseviele erweiterte Funktionen bietet. Es kombiniert Funktionen aus Einfügen, Sprintf und den vorherigen anderen Antworten.

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

Erstellt am 06.03.2019 durch das reprex-Paket (v0.2.1)

Ja, es ist übertrieben für das einfache Beispiel in dieser Frage, aber für viele Situationen mächtig. (siehe https://glue.tidyverse.org/ )

Schnell Beispiel im Vergleich zu pastemit withunten. Der glueCode war etwas einfacher zu tippen und sieht etwas einfacher zu lesen aus.

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

Erstellt am 06.03.2019 durch das reprex-Paket (v0.2.1)

Arthur Yip
quelle