Як можна об'єднати два рядки?


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

Крім того, якщо вашою метою є вихід безпосередньо у файл або stdout, ви можете використовувати 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бібліотеки швидші.
smci

2

Ще одна відповідь без вставки:

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

Де

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

2

glueце нова функція, клас даних та пакет, розроблений як частина tidyverse, з великим розширеним функціоналом. Він поєднує в собі функції з пасти, спринту та інших попередніх відповідей.

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

Створений на 2019-03-06 в пакеті reprex (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 в пакеті reprex (v0.2.1)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.