การรวมสองสตริงสามารถเชื่อมโยงกันได้อย่างไร


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
จริง - แต่คุณสามารถให้แนวทางอื่นซึ่งจัดการปัญหาได้หรือไม่
Rainer

1
ไม่ - คำตอบของคุณถูกต้อง (เหมือนกับคำตอบอื่น ๆ ส่วนใหญ่ที่พูดแบบเดียวกัน) ฉันแค่สังเกตว่าพฤติกรรมของแปะนั้นผิดปกติในความยืดหยุ่นของมัน
naught101

2
@ naught101 ฉันจะไม่คิดว่ามันผิดปกติตามมาตรฐานของ R การรีไซเคิลเวกเตอร์เป็นคุณสมบัติทั่วไปของฟังก์ชัน R เก็บไว้ในใจว่า 'blah' เป็นเวกเตอร์ของความยาว 1. คุณสมบัติรีไซเคิลทำให้มันง่ายที่จะทำสิ่งที่ต้องการที่จะได้รับpaste0("blah", 1:3) "blah1" "blah2" "blah3"
Dason

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 สตริงนั้นจะถูกแทรกที่ส่วนท้ายของแต่ละแถวและเมทริกซ์ทั้งหมดจะยุบลงในสตริงเดี่ยว

เพิ่ม 4/13/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คำตอบอยู่แล้ว?
David Arenburg

4
ในเวลานั้นฉันพบว่ามีประโยชน์ในการสรุปคำตอบหลายคำตอบสำหรับตัวฉันเอง วัตถุประสงค์ไม่ใช่เพื่อรวบรวมคะแนนเสียง แต่เพื่อช่วยให้ผู้อื่นกรองผ่านวิธีแก้ปัญหาที่เสนอมากมาย บ่อยครั้งที่สิ่งที่ฉันกำลังมองหา
Megatron

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

imho ดีกว่ามาก pasteไม่ยืดหยุ่นพอถ้าคุณต้องการผนวกบางสิ่งลงในสตริง
displayname

20

คุณสามารถสร้างผู้ประกอบการของคุณเอง:

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

นอกจากนี้คุณยังสามารถกำหนด&ผู้ประกอบการ'และ' ( ) ใหม่ได้:

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

messing with baseline syntax นั้นน่าเกลียด แต่paste()/paste0()ถ้าหากคุณทำงานกับโค้ดของคุณเองคุณสามารถ (เกือบทุกครั้ง) แทนที่& andตัวดำเนินการเชิงตรรกะด้วย*และทำการคูณค่าตรรกะแทนการใช้ตรรกะ 'และ &'


@ Richard Scriven mayby ​​ฉันไม่เข้าใจ แต่ดูเหมือนจะตรงไปตรงมาเปรียบเทียบ: paste0(as.matrix(iris[1:4]) , as.matrix(iris[1:4]))และas.matrix(iris[1:4]) %&% as.matrix(iris[1:4])
Qbik

ดีมาก ๆ! & เป็นมาตรฐานสำหรับการต่อข้อมูลในหลายภาษาจริง ๆ แล้วฉันคิดว่า R ควรมีไว้เป็นค่าเริ่มต้น ขอแนะนำวิธีนี้อย่างยิ่ง
Serhii

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

glueเป็นฟังก์ชั่นใหม่คลาสข้อมูลและแพ็คเกจที่ได้รับการพัฒนาโดยเป็นส่วนหนึ่งของtidyverseพร้อมฟังก์ชั่นเสริมมากมาย มันรวมคุณสมบัติจากการวาง sprintf และคำตอบอื่น ๆ ก่อนหน้านี้

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)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.