অক্ষর একটি স্ট্রিং মধ্যে আছে কিনা পরীক্ষা করুন


279

আমি স্ট্রিং অন্য স্ট্রিংয়ের উপসেট কিনা তা নির্ধারণ করার চেষ্টা করছি। উদাহরণ স্বরূপ:

chars <- "test"
value <- "es"

"মান" স্ট্রিং "চর" এর অংশ হিসাবে উপস্থিত হলে আমি সত্যটি ফিরিয়ে দিতে চাই। নিম্নলিখিত পরিস্থিতিতে, আমি মিথ্যা ফিরে আসতে চাই:

chars <- "test"
value <- "et"

12
গৃহীত উত্তরটি ভুল, আপনাকে যুক্ত করা দরকার fixed=TRUE, অন্যথায় আপনি স্ট্রিংয়ের পরিবর্তে এটিকে একটি রেজেক্স হিসাবে বিবেচনা করছেন। অক্টোবর 2016 থেকে আমার উত্তর দেখুন
জোশুয়া গাল

@ জোশুয়া চিখ আপনার প্যাটার্নে বিশেষ অক্ষর না থাকলে রেগেক্স ঠিক মতো একই ফলাফল প্রদান করবে will
ব্যবহারকারী 393232000

1
অবশ্যই, তবে আপনি কেবল এটি জানতে পারবেন যে আপনি যদি এটি আক্ষরিক অর্থে পাস করেন। অন্যথায়, আপনি কী কী অক্ষরগুলি প্যাটার্নে রয়েছে তা জানেন না, তাই আপনি হয় ব্যবহার করেন fixed=TRUEবা আপনার কাছে এমন একটি বাগ রয়েছে যা নিঃশব্দে এবং সূক্ষ্মভাবে আপনার ডেটা গোলমাল করবে।
জোশুয়া গাল

উত্তর:


388

greplফাংশনটি ব্যবহার করুন

grepl(value, chars, fixed = TRUE)
# TRUE

?greplআরও জানতে ব্যবহার করুন ।


8
এই সাধারণ ক্ষেত্রে স্থির = সত্যের যোগ করা পারফরম্যান্সের উন্নতি করতে পারে (ধরে নিবেন যে আপনি এই গুণাগুণ প্রচুর পরিমাণে করবেন)।
গ্রেগ স্নো

1
@Josh ও'ব্রায়েন, যে পোস্টে তুলনায় গবেষনার (বেড়ে চলেছে) একটি একক দীর্ঘ স্ট্রিং সব ম্যাচ, খাটো স্ট্রিং একটি গুচ্ছ 1 ম্যাচ খোঁজার চেষ্টা করুন: vec <- replicate(100000, paste( sample(letters, 10, replace=TRUE), collapse='') )
গ্রেগ স্নো

2
@GregSnow - চেষ্টা system.time(a <- grepl("abc", vec))এবং system.time(a <- grepl("abc", vec, fixed=TRUE)), এবং fixed=TRUEএখনও, যদি কিছু কিছুটা মন্থর। এই সংক্ষিপ্ত স্ট্রিংগুলির সাথে পার্থক্যটি প্রশংসনীয় নয় তবে fixed=TRUEএখনও তত দ্রুত বলে মনে হচ্ছে না। এটি নির্দেশ করার জন্য ধন্যবাদ, যদিও এটি দীর্ঘ স্ট্রিংগুলিতে যা fixed=TRUEআসল হিট নেয়।
জোশ ওব্রায়ান

2
grepl (প্যাটার্ন, x) এর অন্তত মধ্যে 2017
JMR

2
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত নয়, কারণ মানটিকে একটি রেজেক্স প্যাটার্ন হিসাবে ব্যাখ্যা করা হবে। স্থির = সত্য সর্বদা ব্যবহার করা উচিত যদি না আপনি যদি স্ট্রিংটি সন্ধান করেন তবে রেজেক্স প্যাটার্নের মতো দেখায় না। নীচে জোশুয়া ক্রিকের উত্তরটির একটি খুব স্পষ্ট ব্যাখ্যা রয়েছে এবং এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।
ভ্যালার

159

উত্তর

দীর্ঘশ্বাস ফেলুন, এই সাধারণ প্রশ্নের উত্তর খুঁজতে আমার 45 মিনিট সময় লেগেছে। উত্তরটা হচ্ছে:grepl(needle, haystack, fixed=TRUE)

# Correct
> grepl("1+2", "1+2", fixed=TRUE)
[1] TRUE
> grepl("1+2", "123+456", fixed=TRUE)
[1] FALSE

# Incorrect
> grepl("1+2", "1+2")
[1] FALSE
> grepl("1+2", "123+456")
[1] TRUE

ব্যাখ্যা

grepলিনাক্স এক্সিকিউটেবলের নামানুসারে নামকরণ করা হয়েছে, যা নিজেই " জি লোবলাল আর এলুলার এক্সপ্রেশন পি রিন্ট " এর একটি সংক্ষিপ্ত বিবরণ , এটি ইনপুটটির লাইনগুলি পড়তে পারে এবং আপনার প্রদত্ত যুক্তিগুলির সাথে মিলে যদি সেগুলি মুদ্রণ করে। "গ্লোবাল" মানে ম্যাচটি ইনপুট লাইনে যে কোনও জায়গায় ঘটতে পারে, আমি নীচে "নিয়মিত এক্সপ্রেশন" ব্যাখ্যা করব, তবে ধারণাটি স্ট্রিংয়ের সাথে মিলানোর জন্য এটি একটি চতুর উপায় (আর এইটিকে "চরিত্র", যেমন class("abc")) বলে এবং "মুদ্রণ" "কারণ এটি একটি কমান্ড লাইন প্রোগ্রাম, আউটপুট নির্গমন করার অর্থ এটি তার আউটপুট স্ট্রিংয়ে মুদ্রণ করে।

এখন, grepপ্রোগ্রামটি মূলত একটি ফিল্টার, ইনপুট লাইন থেকে আউটপুট লাইনে। এবং দেখে মনে হয় যে আর এর grepফাংশন একইভাবে ইনপুটগুলির অ্যারে নেবে। যে কারণে আমার কাছে একেবারে অজানা (আমি কেবল এক ঘন্টা আগে আর এর সাথে খেলতে শুরু করেছি), এটি ম্যাচগুলির তালিকার পরিবর্তে সূচকগুলির একটি ভেক্টরকে ফিরিয়ে দেয় match

তবে, আপনার আসল প্রশ্নে ফিরে আমরা যা চাই তা হ'ল আমরা খড়ের খড়ের মধ্যে একটি সত্য / মিথ্যা মান পেয়েছি কিনা তা জেনে রাখা উচিত। তারা স্পষ্টতই এই ফাংশনটির নামকরণ করার সিদ্ধান্ত নিয়েছিল grepl, যেমন " গ্রেপ" এর মতো তবে " এল ওজিকাল" রিটার্ন মান সহ (তারা সত্য এবং মিথ্যা যৌক্তিক মান বলে, যেমন class(TRUE))।

সুতরাং, এখন আমরা জানি নামটি কোথা থেকে এসেছে এবং এটি করার কথা কি। নিয়মিত এক্সপ্রেশন ফিরে পেতে দেয়। আর্গুমেন্টগুলি, যদিও তারা স্ট্রিং হয়, তারা নিয়মিত অভিব্যক্তি তৈরি করার জন্য ব্যবহৃত হয় (এখন থেকে: রেজেক্স)। একটি রেজেক্স একটি স্ট্রিংয়ের সাথে ম্যাচ করার একটি উপায় (যদি এই সংজ্ঞা আপনাকে বিরক্ত করে তবে তা ছেড়ে দিন)। উদাহরণ হিসেবে বলা যায়, Regex aসাথে মেলে চরিত্র "a", Regex a*চরিত্র মিলে যায় "a"0 বা আরো কয়েকবার, এবং Regex a+চরিত্র মেলে দিবে "a"1 বা বেশি বার। সুতরাং উপরের উদাহরণে, আমরা যে 1+2সূচটি অনুসন্ধান করছি , যখন তাকে রেইজেক্স হিসাবে ধরা হয়, তার অর্থ "এক বা একাধিক 1 এর পরে একটি 2" ... তবে আমাদের পরে একটি প্লাস হয়!

রেজেক্স হিসাবে 1 + 2

সুতরাং, যদি আপনি greplবিনা সেটিং ব্যতীত ব্যবহার করেন তবে fixedআপনার সূঁচগুলি দুর্ঘটনাক্রমে খড়ের খালি হয়ে যাবে এবং এটি ঘটনাক্রমে বেশিরভাগ ক্ষেত্রে কাজ করবে, আমরা দেখতে পাচ্ছি এটি এমনকি ওপি'র উদাহরণের জন্যও কাজ করে। তবে এটি একটি সুপ্ত বাগ! আমাদের এটি জানাতে হবে ইনপুটটি একটি স্ট্রিং, কোনও রেজেক্স নয়, যা আপাতদৃষ্টিতে যা প্রয়োজন fixedতা। কেন স্থির? কোনও ক্লু নেই, বুকমার্ক করুন এই উত্তরটি খ / সি আপনি মুখস্থ করার আগে আপনাকে সম্ভবত এটি আরও 5 বার সন্ধান করতে হবে।

কয়েকটি চূড়ান্ত চিন্তা

আপনার কোডটি যত ভাল হবে তা বোঝার জন্য আপনাকে যত কম ইতিহাস জানতে হবে। প্রতিটি যুক্তির কমপক্ষে দুটি আকর্ষণীয় মান থাকতে পারে (অন্যথায় এটি একটি যুক্তি হওয়ার প্রয়োজন হবে না), ডক্স এখানে 9 টি যুক্তি তালিকাভুক্ত করে যার অর্থ এটি কমপক্ষে কমপক্ষে 2 ^ 9 = 512 উপায় রয়েছে, এটি অনেক কাজ লিখুন, পরীক্ষা করুন এবং মনে রাখবেন ... এই জাতীয় ক্রিয়াকলাপগুলি দ্বিগুণ করুন (এগুলিকে বিভক্ত করুন, একে অপরের উপর নির্ভরশীলতা সরিয়ে দিন, স্ট্রিং জিনিসগুলি ভেক্টর জিনিসের চেয়ে আলাদা) ge কিছু অপশনও পারস্পরিক একচেটিয়া, ব্যবহারকারীদের কোড ব্যবহারের ভুল উপায়গুলি দেবেন না, যেমন সমস্যাযুক্ত প্রার্থনাটি কাঠামোগত অযৌক্তিক হওয়া উচিত (যেমন কোনও বিকল্প নেই যা অস্তিত্বহীন নয়) যুক্তিযুক্তভাবে অযৌক্তিক নয় (যেখানে আপনাকে করতে হবে এটি ব্যাখ্যা করতে একটি সতর্কতা প্রেরণ করুন)। রূপকভাবে রাখুন: দশম তলার পাশের সামনের দরজাটি একটি প্রাচীরের সাথে প্রতিস্থাপন করা এমন একটি চিহ্নকে ঝুলিয়ে দেওয়ার চেয়ে ভাল যা এর ব্যবহারের বিরুদ্ধে সতর্ক করে, তবে হয় উভয়ের চেয়ে ভাল। একটি ইন্টারফেসে, ফাংশনটি সংজ্ঞায়িত করে যে আর্গুমেন্টগুলি দেখতে কেমন হবে, কলার নয় (কারণ কলার ফাংশনের উপর নির্ভর করে, যার দ্বারা কল করা যেতে পারে এমন সমস্ত কিছুর উপর নির্ভর করে ফাংশনটি কলকারীদের উপরও নির্ভর করে এবং এই ধরণের চক্রীয় নির্ভরতা দ্রুত কোনও সিস্টেমকে আটকে দেবে এবং আপনি যে সুবিধাটি প্রত্যাশা করছেন তা কখনই সরবরাহ করবে না)। দ্বিখণ্ডিত প্রকার সম্পর্কে খুব সতর্ক থাকুন, এটি এমন একটি ডিজাইনের ত্রুটি যা পছন্দ করে প্রত্যেকে এটির সাথে কল করতে চাইলে এমন সমস্ত কিছু অনুমান করা ফাংশনটি কলকারীদের উপরও নির্ভর করে এবং এই ধরণের চক্রীয় নির্ভরতা দ্রুত কোনও সিস্টেমকে আটকে রাখবে এবং আপনার প্রত্যাশাগুলি কখনই সরবরাহ করবে না)। দ্বিখণ্ডিত প্রকার সম্পর্কে খুব সতর্ক থাকুন, এটি এমন একটি ডিজাইনের ত্রুটি যা পছন্দ করে প্রত্যেকে যার সাথে এটি কল করতে চাইতে পারে তার সমস্ত কিছু অনুমান করা ফাংশনটি কলকারীদের উপরও নির্ভর করে এবং এই ধরণের চক্রীয় নির্ভরতা দ্রুত কোনও সিস্টেমকে আটকে রাখবে এবং আপনার প্রত্যাশাগুলি কখনই সরবরাহ করবে না)। দ্বিখণ্ডিত প্রকার সম্পর্কে খুব সতর্ক থাকুন, এটি এমন একটি ডিজাইনের ত্রুটি যা পছন্দ করেTRUEএবং 0এবং "abc"সমস্ত ভেক্টর হয়।


6
আপনার ব্যাখ্যা জন্য চিয়ার্স! এটি आर-এর দীর্ঘ সময় ধরে বিকশিত হয় এবং কিছু অদ্ভুত নকশার পছন্দগুলির সাথে আটকে থাকে (উদাহরণস্বরূপ value মানের ধরণের ক্ষেত্রে এই প্রশ্নের উত্তর )। যাইহোক, ম্যাচ সূচকগুলির একটি ভেক্টরকে ফিরিয়ে আনা এই ক্ষেত্রে উপযুক্ত বলে মনে হয় grepযেমন সারিগুলি ফিল্টার করা হয়, কোষগুলি নয়।
krevelen

4
"স্থির" বলতে "স্থির" ক্রমের সাথে মেলে এমন অক্ষরকে বোঝায়।
উইল Beason

32

আপনি চান grepl:

> chars <- "test"
> value <- "es"
> grepl(value, chars)
[1] TRUE
> chars <- "test"
> value <- "et"
> grepl(value, chars)
[1] FALSE

27

stringiপ্যাকেজ থেকে এই ফাংশনটি ব্যবহার করুন :

> stri_detect_fixed("test",c("et","es"))
[1] FALSE  TRUE

কিছু মানদণ্ড:

library(stringi)
set.seed(123L)
value <- stri_rand_strings(10000, ceiling(runif(10000, 1, 100))) # 10000 random ASCII strings
head(value)

chars <- "es"
library(microbenchmark)
microbenchmark(
   grepl(chars, value),
   grepl(chars, value, fixed=TRUE),
   grepl(chars, value, perl=TRUE),
   stri_detect_fixed(value, chars),
   stri_detect_regex(value, chars)
)
## Unit: milliseconds
##                               expr       min        lq    median        uq       max neval
##                grepl(chars, value) 13.682876 13.943184 14.057991 14.295423 15.443530   100
##  grepl(chars, value, fixed = TRUE)  5.071617  5.110779  5.281498  5.523421 45.243791   100
##   grepl(chars, value, perl = TRUE)  1.835558  1.873280  1.956974  2.259203  3.506741   100
##    stri_detect_fixed(value, chars)  1.191403  1.233287  1.309720  1.510677  2.821284   100
##    stri_detect_regex(value, chars)  6.043537  6.154198  6.273506  6.447714  7.884380   100

22

এছাড়াও, "স্ট্রিংগার" লাইব্রেরি ব্যবহার করে করা যেতে পারে :

> library(stringr)
> chars <- "test"
> value <- "es"
> str_detect(chars, value)
[1] TRUE

### For multiple value case:
> value <- c("es", "l", "est", "a", "test")
> str_detect(chars, value)
[1]  TRUE FALSE  TRUE FALSE  TRUE

20

কেবলমাত্র যদি আপনিও পরীক্ষা করতে চান যে কোনও স্ট্রিংয়ে (বা স্ট্রিংয়ের সেটে) একাধিক সাব-স্ট্রিং রয়েছে, আপনি '|' ব্যবহার করতে পারেন দুটি সাবস্ট্রিংয়ের মধ্যে।

>substring="as|at"
>string_vector=c("ass","ear","eye","heat") 
>grepl(substring,string_vector)

তুমি পাবে

[1]  TRUE FALSE FALSE  TRUE

যেহেতু প্রথম শব্দের মধ্যে "হিসাবে" বিস্তৃত থাকে এবং শেষ শব্দটিতে "এ" থাকে


ওআর অপারেটরটি ঠিক আমার প্রয়োজন মতো ছিল! +1
সাম

10

ব্যবহার করুন grepবা grepl তবে আপনি নিয়মিত এক্সপ্রেশন ব্যবহার করতে চান কিনা তা সম্পর্কে সচেতন হন

ডিফল্টরূপে grepএবং সম্পর্কিতগুলি মিলের জন্য নিয়মিত ভাব প্রকাশ করে, আক্ষরিক স্ট্রাস্টিং নয়। আপনি যদি এটির প্রত্যাশা না করে থাকেন এবং আপনি কোনও অবৈধ রেজেক্সের সাথে মিলের চেষ্টা করেন, এটি কার্যকর হয় না:

> grep("[", "abc[")
Error in grep("[", "abc[") : 
  invalid regular expression '[', reason 'Missing ']''

সত্যিকারের সাবস্ট্রিং পরীক্ষা করতে, ব্যবহার করুন fixed = TRUE

> grep("[", "abc[", fixed = TRUE)
[1] 1

আপনি যদি রিজেক্স চান, দুর্দান্ত, তবে ওপি এটি জিজ্ঞাসা করে বলে মনে হচ্ছে না।


7

তুমি ব্যবহার করতে পার grep

grep("es", "Test")
[1] 1
grep("et", "Test")
integer(0)

0

এখানে অনুরূপ সমস্যা: একটি স্ট্রিং এবং কীওয়ার্ডগুলির একটি তালিকা দেওয়া, কীওয়ার্ডগুলির মধ্যে স্ট্রিংয়ের মধ্যে কোনটি রয়েছে তা সনাক্ত করুন।

এই থ্রেড থেকে প্রস্তাবনাগুলি stringrএর str_detectএবং grepl। এখানে থেকে মানদণ্ড দেওয়া হচ্ছেmicrobenchmarkপ্যাকেজটির :

ব্যবহার

map_keywords = c("once", "twice", "few")
t = "yes but only a few times"

mapper1 <- function (x) {
  r = str_detect(x, map_keywords)
}

mapper2 <- function (x) {
  r = sapply(map_keywords, function (k) grepl(k, x, fixed = T))
}

এবং তারপর

microbenchmark(mapper1(t), mapper2(t), times = 5000)

আমরা খুঁজি

Unit: microseconds
       expr    min     lq     mean  median      uq      max neval
 mapper1(t) 26.401 27.988 31.32951 28.8430 29.5225 2091.476  5000
 mapper2(t) 19.289 20.767 24.94484 23.7725 24.6220 1011.837  5000

আপনি দেখতে পাচ্ছেন, কীওয়ার্ড অনুসন্ধানের 5000 টিরও বেশি পুনরাবৃত্তি ব্যবহার করে str_detectএবং greplব্যবহারিক স্ট্রিং এবং কীওয়ার্ডের ভেক্টর ব্যবহার greplকরে এর চেয়ে কিছুটা ভাল সম্পাদন করে str_detect

ফলাফলটি বুলিয়ান ভেক্টর r যা সনাক্ত করে যে কী কীওয়ার্ডগুলিতে স্ট্রিং রয়েছে।

অতএব, আমি greplকোনও কীওয়ার্ড স্ট্রিংয়ে আছে কিনা তা নির্ধারণ করার জন্য ব্যবহার করার পরামর্শ দিচ্ছি ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.