Как можно объединить две строки?


375

Как я могу объединить (объединить, объединить) два значения? Например у меня есть:

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

Моя цель - объединить два значения в «tmp» в одну строку:

tmp_new = "GAD,AB"

Какая функция может сделать это для меня?


Большинство ответов здесь ломаются, если строки являются векторами, как отмечается в ответе @ RichardScriven.
smci

@smci как насчет небольшого ответа, который я отправил? какие-либо предложения, чтобы улучшить это?
joel.wilson

Ответы:


505
paste()

это путь Как указывалось в предыдущих постерах, паста может делать две вещи:

объединить значения в одну «строку», например

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

где аргумент sepуказывает символ (ы), который будет использоваться между аргументами для объединения или свертывания векторов символов

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

где аргумент collapseуказывает символ (ы), который будет использоваться между элементами вектора, который будет свернут.

Вы даже можете комбинировать оба:

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

Надеюсь это поможет.


9
Смешивание строк и векторов или векторов различной длины слишком гибко paste()для меня. Например, paste(c('a','b'),'blah', c(1,2,3))результаты в "a blah 1" "b blah 2" "a blah 3". По сути, он создает вектор строк такой же длины, что и самый длинный вектор, который был передан, и зацикливает другие векторы / строки на ту же длину. Там много места для случайного поведения.
naught101

1
Верно - но можете ли вы предоставить альтернативный подход, который решает вопрос?
Райнер

1
нет - ваш ответ правильный (как и большинство других ответов, которые говорят то же самое). Я просто заметил, что поведение пасты необычно в своей гибкости.
naught101

2
@ naught101 Я бы не стал считать это необычным по стандартам R. Переработка векторов является общим свойством функций R. Имейте в виду , что «мля» есть вектор длины 1. рециркуляция свойство делает его легко сделать что - то подобное , paste0("blah", 1:3)чтобы получить "blah1" "blah2" "blah3".
Дейсон

5
Да, я должен жаловаться на R, а не просто вставлять: P. Это на самом деле противоречиво в R - data.frame()не позволяет вам сделать это, если векторы не кратны друг другу. matrix()выкладывает предупреждения, но array()не делает. Вид раздражает. На самом деле, они все должны выдавать предупреждения, если не установлена ​​какая-либо опция ...
naught101

85

help.search() это удобная функция, например,

> help.search("concatenate")

приведет тебя к paste().


42

Для первого отсутствия paste()ответа мы можем посмотреть stringr::str_c()(и затем toString()ниже). Этот вопрос уже давно не существует, поэтому я считаю полезным упомянуть, что он также существует.

Очень прост в использовании, как вы можете видеть.

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

Из описания файла документации, он прекрасно подходит для этой проблемы.

Чтобы понять, как работает str_c, вам нужно представить, что вы строите матрицу строк. Каждый входной аргумент формирует столбец и расширяется до длины самого длинного аргумента, используя обычные правила повторного использования. Строка sep вставляется между каждым столбцом. Если свернуть NULL, каждая строка свернута в одну строку. Если не NULL, эта строка вставляется в конец каждой строки, и вся матрица сворачивается в одну строку.

Добавлено 13.04.2016 : Это не совсем то же самое, что и желаемый результат (дополнительное пространство), но никто также не упомянул об этом. toString()это в основном версия paste()с collapse = ", "жестким кодом, так что вы можете сделать

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

3
Хех, это единственный ответ, который касается того факта, что tmp является вектором, а не просто набором значений - pasteне работает с векторами. Другой вариант есть do.call(paste, as.list(tmp)).
naught101

35

Как уже отмечали другие, paste()это путь. Но это может раздражать необходимость вводить paste(str1, str2, str3, sep='')каждый раз, когда вы хотите разделитель не по умолчанию.

Вы можете очень легко создавать функции-оболочки, которые делают жизнь намного проще. Например, если вы обнаружите, что действительно часто объединяете строки без разделителя, вы можете сделать:

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

или если вы часто хотите объединить строки из вектора (например, implode()из PHP):

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

Позволяет вам сделать это:

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

Также есть встроенный модуль paste0, который делает то же самое, что и мой implode, но без использования пользовательских разделителей. Это немного более эффективно, чем paste().



28

В качестве альтернативы, если вашей целью является вывод непосредственно в файл или стандартный вывод, вы можете использовать cat:

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

4
Так какой смысл публиковать pasteответ через 4 года, когда уже есть около десятка pasteответов?
Дэвид Аренбург

4
В то время я нашел полезным обобщить несколько ответов для себя. Цель состояла не в том, чтобы собрать голоса, но чтобы помочь другим отфильтровать множество предлагаемых решений. Часто это то, что я ищу.
Мегатрон

22

Другой путь:

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

Это иногда полезно, чем paste()функция. %sобозначает место, где субъективные строки будут включены.

Обратите внимание, что это пригодится, когда вы попытаетесь построить путь:

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

вывод

/this/is/a/path

для программистов на C, работающих с R, sprintf знаком и полезен для "объединения двух строк"
subsci

Намного лучше, имхо. pasteнедостаточно гибок, если вы хотите добавить что-то к строке.
displayname

20

Вы можете создать свой собственный оператор:

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

Вы также можете переопределить &операторы 'и' ( ):

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

возиться с базовым синтаксисом некрасиво, но при использовании, paste()/paste0()если вы работаете только со своим собственным кодом, вы можете (почти всегда) заменить логический & andоператор *и сделать умножение логических значений вместо использования логических 'и &'


@Richard Scriven Может, я не понимаю, но это кажется простым, сравните: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))иas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik

очень очень хорошо! & является стандартным для объединения во многих языках, я действительно думаю, что R должен был иметь его по умолчанию. Настоятельно рекомендую этот путь
Сергей

14

Учитывая матрицу tmp, которую вы создали:

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

Я предполагаю, что есть некоторая причина, почему вы создаете матрицу с использованием cbind, а не просто:

tmp <- "GAD,AB"

3

Рассмотрим случай, когда строки являются столбцами, а результатом должен быть новый столбец:

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

При желании пропустите [c("a", "b")]подмножество, если нужно вставить все столбцы.

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

Хорошо, но stringi, stringrбиблиотеки быстрее.
СМС

2

Еще один не вставленный ответ:

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

куда

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

2

glueэто новая функция, класс данных и пакет, который был разработан как часть tidyverse, с большим количеством расширенной функциональности. Он сочетает в себе функции из paste, sprintf и других предыдущих ответов.

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

Создано 2019-03-06 пакетом представлением (v0.2.1)

Да, для простого примера в этом вопросе это излишне, но для многих ситуаций это просто. (см. https://glue.tidyverse.org/ )

Быстрый пример по сравнению pasteс withниже. glueКод был немного проще набрать и выглядит немного легче читать.

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

Создано 2019-03-06 пакетом представлением (v0.2.1)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.