2016-08-04 5 views
12

私は文字列のベクトルを持っていて、すべての文字列の共通部分文字列を異なる部分文字列で置き換えたいと思います。私は、例えばR.でこれをやっている:1つの部分文字列をRの部分文字列で置き換えるにはどうすればよいですか?

input=c("I like fruits","I like you","I like dudes") 
# I need to do something like this 
newStrings=c("You","We","She") 
gsub("I",newStrings,input) 

出力のようになりますように。しかし、GSUBはnewStringsで唯一の最初の文字列を使用しています

"You like fruits" 
"We like you" 
"She like dudes" 

。助言がありますか? おかげ

+0

すごい非常に多くのさまざまなソリューション、感謝のためsapplyを使用することができます! – Mohammad

+1

文字列の先頭または末尾の文字列を置換したいだけですか? 'I'が文字列に何度か現れるとどうなりますか? –

+0

@DavidArenburg良い点は、「私」が何回でもどこにでも出現する場合を考えたかったのです。私の例は少し誤解を招くかもしれないと思います。 – Mohammad

答えて

14

あなたはstringrを使用することができます。

stringr::str_replace_all(input, "I" ,newStrings) 

[1] "You like fruits" "We like you"  
[3] "She like dudes" 

またはデビッドArenburg @によって提案されたとして:

stringi::stri_replace_all_fixed(input, "I", newStrings) 

Benchmrk

library(stringi) 
library(stringr) 
library(microbenchmark) 

set.seed(123) 
x <- stri_rand_strings(1e3, 10) 
y <- stri_rand_strings(1e3, 1) 

identical(stringi::stri_replace_all_fixed(x, "I", y), stringr::str_replace_all(x, fixed("I") , y)) 
# [1] TRUE 
identical(stringi::stri_replace_all_fixed(x, "I", y), diag(sapply(y, gsub, pattern = "I", x = x, fixed = TRUE))) 
# [1] TRUE 
identical(stringi::stri_replace_all_fixed(x, "I", y), mapply(gsub, "I", y, x, USE.NAMES = FALSE, fixed = TRUE)) 
# [1] TRUE 

microbenchmark("stingi: " = stringi::stri_replace_all_fixed(x, "I", y), 
       "stringr (optimized): " = stringr::str_replace_all(x, fixed("I") , y), 
       "base::mapply (optimized): " = mapply(gsub, "I", y, x, USE.NAMES = FALSE, fixed = TRUE), 
       "base::sapply (optimized): " = diag(sapply(y, gsub, pattern = "I", x = x, fixed = TRUE))) 

# Unit: microseconds 
#      expr  min   lq  mean  median   uq  max neval cld 
#     stingi:  132.156 137.1165 171.5822 150.3960 194.2345 460.145 100 a 
#  stringr (optimized):  801.894 828.7730 947.1813 912.6095 968.7680 2716.708 100 a 
# base::mapply (optimized): 2827.104 2946.9400 3211.9614 3031.7375 3123.8940 8216.360 100 a 
# base::sapply (optimized): 402349.424 476545.9245 491665.8576 483410.3290 513184.3490 549489.667 100 b 
+1

ニース!これは私の答えよりもコンパクトです。 –

+1

@MikeyMike、あなたの方がより一般的なアプローチです。 – Sumedh

+2

すぐにベンチマークで投稿を編集します。 –

7

mapply()これらの場合に非常に便利になります

mapply(sub, "I", newStrings, input, USE.NAMES = FALSE,fixed=T) 
# [1] "You like fruits" "We like you"  "She like dudes" 
+1

あなたのコードを(1) 'mapply()'に編集して、unlist()、(2) 'USE.NAMES = FALSE'を避けて' unname() 'を避け、(3)不要な無名関数を削除しました。今はすべてが1回の呼び出しです。 –

+1

たぶん 'fixed = TRUE'を追加する –

+1

確かに、そこにも投げてください!ハハ。私は 'sub()'にも変更します。私は彼に残りの部分を見せさせるでしょう;) –

2

をあなたはすべてこの

diag(sapply(newStrings,gsub,pattern="I",x=input)) 
1つの問題のため
+3

メモリとパフォーマンスの両方が非常に非効率的です –

関連する問題