एक विशेष स्ट्रिंग में एक पैटर्न के कई उदाहरण हो सकते हैं जिन्हें मैं मिलान करने का प्रयास कर रहा हूं। उदाहरण के लिए, यदि मेरा पैटर्न <N(.+?)N> है और मेरी स्ट्रिंग "My name is <N Timon N> and his name is <N Pumba N>" है, तो दो मैच हैं। मैं प्रत्येक मैच को एक प्रतिस्थापन के साथ बदलना चाहता हूं जिसमें एक इंडेक्स शामिल है जिसके लिए मैच को बदला जा रहा है।

तो मेरी स्ट्रिंग में "My name is <N Timon N> and his name is <N Pumba N>", मैं स्ट्रिंग को "My name is [Name #1] and his name is [Name #2]" पढ़ने के लिए बदलना चाहता हूं।

मैं इसे कैसे पूरा करूं, अधिमानतः एक समारोह के साथ? और अधिमानतः stringr या stringi के कार्यों का उपयोग करना?

1
bschneidr 2 नवम्बर 2017, 18:33

4 जवाब

सबसे बढ़िया उत्तर

आप इसे आधार R में gregexpr और regmatches के साथ कर सकते हैं:

my_string = "My name is <N Timon N> and his name is <N Pumba N>"

# Get the positions of the matches in the string
m = gregexpr("<N(.+?)N>", my_string, perl = TRUE)

# Index each match and replace text using the indices
match_indices = 1:length(unlist(m))

regmatches(my_string, m) = list(paste0("[Name #", match_indices, "]"))

परिणाम:

> my_string
# [1] "My name is [Name #1] and his name is [Name #2]"

नोट:

यह समाधान एक ही मिलान को एक अलग "नाम" के रूप में मानता है यदि यह एक से अधिक बार प्रकट होता है। उदाहरण के लिए निम्नलिखित:

my_string = "My name is <N Timon N> and his name is <N Pumba N>, <N Timon N> again"


m = gregexpr("<N(.+?)N>", my_string, perl = TRUE)

match_indices = 1:length(unlist(m))

regmatches(my_string, m) = list(paste0("[Name #", match_indices, "]"))

आउटपुट:

> my_string
[1] "My name is [Name #1] and his name is [Name #2], [Name #3] again"
3
avid_useR 2 नवम्बर 2017, 21:01

यहां एक समाधान दिया गया है जो gsubfn और proto पैकेज पर निर्भर करता है।

# Define the string to which the function will be applied
my_string <- "My name is <N Timon N> and his name is <N Pumba N>"

# Define the replacement function
replacement_fn <- function(x) {

  replacment_proto_fn <- proto::proto(fun = function(this, x) {
      paste0("[Name #", count, "]")
  })

  gsubfn::gsubfn(pattern = "<N(.+?)N>",
                 replacement = replacment_proto_fn,
                 x = x)
}

# Use the function on the string
replacement_fn(my_string)
2
bschneidr 2 नवम्बर 2017, 18:33

यहां dplyr + stringr के साथ एक अलग तरीका दिया गया है:

library(dplyr)
library(stringr)

string %>%
  str_extract_all("<N(.+?)N>") %>%
  unlist() %>%
  setNames(paste0("[Name #", 1:length(.), "]"), .) %>%
  str_replace_all(string, .)

# [1] "My name is [Name #1] and his name is [Name #2]"

नोट:

दूसरा समाधान str_extract_all के साथ मैचों को निकालता है, फिर मैचों का उपयोग प्रतिस्थापन के नामित वेक्टर बनाने के लिए करता है, जिसे अंततः खोजने और बदलने के लिए str_replace_all में फीड किया जाता है।

जैसा कि ओपी द्वारा बताया गया है, यह समाधान कुछ मामलों में gregexpr + regmatches दृष्टिकोण से भिन्न परिणाम देता है। उदाहरण के लिए निम्नलिखित:

string = "My name is <N Timon N> and his name is <N Pumba N>, <N Timon N> again"

string %>%
  str_extract_all("<N(.+?)N>") %>%
  unlist() %>%
  setNames(paste0("[Name #", 1:length(.), "]"), .) %>%
  str_replace_all(string, .)

आउटपुट:

[1] "My name is [Name #1] and his name is [Name #2], [Name #1] again"
1
avid_useR 2 नवम्बर 2017, 20:59

सरल, शायद धीमा, लेकिन काम करना चाहिए:

ct <- 1
while(TRUE) {
 old_string <- my_string; 
 my_string <- stri_replace_first_regex(my_string, '\\<N.*?N\\>', 
       paste0('[name', ct, ,']')); 
  if (old_string == my_string) break 
  ct <- ct + 1
}
0
user3603486user3603486 2 नवम्बर 2017, 19:15