ट्रैक
/
R
R
/
अभ्यास
/
लॉग लेवल
लॉग लेवल

लॉग लेवल

सीखने का अभ्यास

परिचय

पृष्ठभूमि

स्ट्रिंग टेक्स्ट का एक टुकड़ा होती है, जो कोटेशन चिह्नों के बीच लिखा जाता है। R का हर वर्तमान में समर्थित वर्ज़न स्ट्रिंग को UTF-8 में एन्कोड करता है, इसलिए दुनिया की ज़्यादातर भाषाएँ समर्थित की जा सकती हैं।

mystring <- "some text"
mystring
#> [1] "some text"
typeof(mystring)
#> [1] "character"

दुर्भाग्य से, दूसरी भाषाओं से परिचित प्रोग्रामरों को यह शब्दावली भ्रमित कर सकती है।

हालाँकि type character होता है, R एक अकेले अक्षर (जिसे कई दूसरी भाषाओं में char कहा जाता है, पर R में नहीं) और एक लंबी स्ट्रिंग के बीच कोई अंतर नहीं करता। दोनों एक ही आइटम होते हैं, और सिंगल ' ' या डबल " " कोटेशन चिह्नों में बिना अंतर के रखे जा सकते हैं।

स्टाइल गाइड डबल कोटेशन इस्तेमाल करने की सलाह देती है, सिवाय उस स्थिति के जब आप स्ट्रिंग के अंदर डबल कोटेशन बिना एस्केप किए इस्तेमाल करना चाहते हों।

str2 <- 'String with "quotes"'  # convenience format
str2
#> [1] "String with \"quotes\""    # standard format

इस तरह एक character vector स्ट्रिंग का वेक्टर होता है, जिसमें हर स्ट्रिंग एक अकेला एलिमेंट होती है।

s <- c("some", "strings")
s
#> [1] "some"    "strings"
length(s)
#> [1] 2
length(s[1])  # the number of vector elements, not the string length
#> [1] 1

nchar(s[1])  # the number of characters in the string "some"
#> [1] 4

ऊपर के उदाहरण में length(s[1]) और length("some") एक जैसे हैं: यह वेक्टर एलिमेंट की संख्या है, स्ट्रिंग की लंबाई नहीं।

किसी एक स्ट्रिंग पर काम करना निश्चित रूप से संभव है, जैसे ऊपर के उदाहरण में nchar() से, लेकिन इसके लिए कुछ खास फंक्शन चाहिए, जिनकी चर्चा आगे की जाएगी।

स्ट्रिंग फंक्शन

बेस R में ज़्यादातर चीज़ें संभव हैं, लेकिन बहुत से प्रोग्रामरों को स्ट्रिंग पर काम करने का समर्थन काफी सीमित और भ्रमित करने वाला लगता है।

सौभाग्य से, tidyverse के पैकेज हैं जो कहीं ज़्यादा सहज, लचीले और आपस में एकरूप हैं।

बेस R

अभी भी बहुत सारा पुराना कोड है जो पुराने ढंग के स्ट्रिंग फंक्शन इस्तेमाल करता है। इसमें Exercism पर मौजूद ज़्यादातर समुदाय के हल शामिल हैं।

इसके अलावा, छोटे-छोटे कामों के लिए बड़ी लाइब्रेरी इम्पोर्ट करने की बजाय बिल्ट-इन फंक्शन इस्तेमाल करना काम का हो सकता है। अभ्यासों को जाँचने के लिए उदाहरण हल लिखते समय R ट्रैक के मेंटेनर आम तौर पर यही तरीका अपनाते हैं।

इसलिए पुराने तरीकों का थोड़ा ज्ञान अब भी सीखने लायक है।

nchar

स्ट्रिंग में अक्षरों की संख्या लौटाता है।

nchar("string")
#> [1] 6

nchar("Hrōðgār") # a person in Beowulf, written in Old English
#> [1] 7

"अक्षर" का मतलब क्या है, यह (जटिल!) विषय हमारे दायरे से बाहर है। ऊपर के उदाहरणों में बस दो-तीन बातें ध्यान में रखिए:

  • हालाँकि अंदर से ये C में लागू किए गए हैं, R में स्ट्रिंग \0 पर खत्म नहीं होतीं (जो लंबाई में 1 जोड़ देता)।
  • मल्टी-बाइट यूनिकोड अक्षरों को वैसे ही संभाला जाता है जैसी आप अपेक्षा/उम्मीद करते हैं। "Hrōðgār" में 7 अक्षर हैं (जिन्हें "रून" या "कोड पॉइंट" भी कहते हैं), लेकिन इसे स्टोर करने के लिए 10 बाइट चाहिए।
paste और paste0

किसी भी संख्या में स्ट्रिंग को जोड़कर एक स्ट्रिंग बनाता है।

चाहें तो paste के लिए सेपरेटर तय कर सकते हैं: डिफ़ॉल्ट एक स्पेस है।

paste0(v) और paste(v, sep = "") एक जैसे हैं।

paste("bits", "of", "a", "string")
#> [1] "bits of a string"
paste0("bits", "of", "a", "string")
#> [1] "bitsofastring"
sprintf

स्ट्रिंग जोड़ने पर ज़्यादा बारीक नियंत्रण के लिए R ने sprintf फंक्शन C से लिया है (और कई बाद की भाषाओं ने भी: विकिपीडिया पर इनकी सूची लगभग 30 है)।

r <- 5.3
pi <- 3.14159
sprintf("A circle of radius %.1f has area %.2f", r, pi * r^2)
#> [1] "A circle of radius 5.3 has area 88.25"
trimws

आगे और/या पीछे की खाली जगह trimws() से हटाई जा सकती है:

s <- "    messy string   "
trimws(s)
#> [1] "messy string"

दोनों सिरों को न छूने के लिए which = "left" (या "right") पैरामीटर मौजूद है।

substr

यह एक अकेली स्ट्रिंग पर काम करता है और दो सीमाओं (दोनों समेत) के बीच की सबस्ट्रिंग लौटाता है।

substr("Exercism", 5, 7)
#> [1] "cis"
strsplit

यह एक स्ट्रिंग को सेपरेटर स्ट्रिंग के आधार पर R की लिस्ट में बाँटता है। सेपरेटर देना ज़रूरी है (इसका कोई डिफ़ॉल्ट नहीं है), पर यह खाली स्ट्रिंग भी हो सकता है।

strsplit("R, Python, Julia", ", ")
[[1]]
#> [1] "R"      "Python" "Julia" 

strsplit("Exercism", "")
[[1]]
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"

लिस्ट पर एक अलग कॉन्सेप्ट में चर्चा होगी। अगर आप सिलेबस के उस हिस्से तक अभी नहीं पहुँचे हैं, तो अभी इतना जान लीजिए कि unlist() फंक्शन (इस मामले में) लिस्ट को वेक्टर में बदल देगा।

unlist(strsplit("Exercism", ""))
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"

Tidyverse

उदारता से कहें तो पुराने ढंग के स्ट्रिंग फंक्शन R की सबसे अच्छी चीज़ नहीं हैं (कम उदार राय भी मौजूद हैं)।

स्थिति सुधारने के लिए stringr लाइब्रेरी 2009 से विकसित हो रही है, और अब Tidyverse संग्रह का अहम हिस्सा है।

इसे library(stringr) या library(tidyverse) से अपने नेमस्पेस में इम्पोर्ट कीजिए।

इसकी कुछ प्रमुख विशेषताएँ ये हैं:

  • सभी फंक्शन के नामों में str_ प्रीफ़िक्स होता है और वे अपना उद्देश्य साफ़ रखने की कोशिश करते हैं।
  • आर्गुमेंट का क्रम खुद में एकरूप रखने की कोशिश की गई है, जिसमें इनपुट डेटा पहला आर्गुमेंट होता है।
  • इनपुट एक अकेली स्ट्रिंग से लेकर जटिल डेटा स्ट्रक्चर तक कुछ भी हो सकते हैं। फंक्शन खुद को ढालकर सबसे समझदारी वाला काम करने की कोशिश करते हैं।

Tidyverse के बाकी सारे पैकेजों की तरह stringr का दस्तावेज़ीकरण भी अच्छा है, जो आम तौर पर पैकेज के लेखकों ने ही लिखा है।

विषयांतर: पाइप का छोटा परिचय

फंक्शन को जोड़ने के लिए पाइप |> के इस्तेमाल पर सिलेबस के दूसरे हिस्सों में ज़्यादा विस्तार से चर्चा होगी।

अभी के लिए इतना जानना काम का है:

  • पाइप के बाईं ओर का परिणाम दाईं ओर के फंक्शन का पहला आर्गुमेंट बन जाता है (यहाँ "दाईं ओर" में ज़रूरी न होने वाले लाइन ब्रेक नहीं गिने जाते)।
  • बाकी बचे आर्गुमेंट फंक्शन कॉल में शामिल किए जा सकते हैं।
  • R में हमें किसी फंक्शन के कॉल पर पाइप करना होता है, सिर्फ नाम पर नहीं, इसलिए ब्रैकेट हमेशा ज़रूरी होते हैं (यह कुछ दूसरी भाषाओं से अलग है)।

नीचे का उदाहरण इस सिंटैक्स को दिखाता है। अलग-अलग फंक्शन की चर्चा आगे की जाएगी।

library(stringr)

"Monday-25-February" |> 
  str_split("-") |>     
  unlist() |>               # [1] "Monday"   "25"       "February"
  str_sub(1, 3) |>          # [1] "Mon" "25"  "Feb"
  str_to_upper() |>         # [1] "MON" "25"  "FEB"
  str_flatten(collapse = ", ")
#> [1] "MON, 25, FEB"
लंबाई संभालना

str_length कोड पॉइंट गिनता है (nchars जैसा)।

खाली जगह से जुड़े कई दूसरे फंक्शन भी हैं, जिनमें str_trim() और str_squish() शामिल हैं। किसी भी डेटा साइंस प्रोजेक्ट की शुरुआत में यह अक्सर सफाई का बहुत ज़रूरी काम होता है।

# The first 3 kernels in JuPyteR notebooks:
str_length(c("Julia", "Python", "R"))           #> [1] 1 6 5
#> [1] 5 6 1
str_pad(c("Julia", "Python", "R"), 8, "right")  # add spaces if necessary
#> [1] "Julia   " "Python  " "R       "

str_trim("Julia    Python    R    ")   # remove leading & trailing whitespace
#> [1] "Julia    Python    R"
str_squish("Julia   Python  R    ")  # trim, collapse multiple spaces 
#> [1] "Julia Python R"
स्ट्रिंग का सबसेट निकालना

str_sub(string, start, end) फंक्शन start से end तक (दोनों समेत) की सबस्ट्रिंग लौटाता है, जबकि str_sub_all() एक साथ कई स्ट्रिंग पर काम कर सकता है।

इसमें काफी लचीलापन है। start और end का डिफ़ॉल्ट क्रमशः पहला और अंतिम अक्षर होता है। ये इंडेक्स के वेक्टर हो सकते हैं। वेक्टर इंडेक्सिंग के उलट, जो अच्छी बात है, ऋणात्मक मान स्ट्रिंग के अंत से पीछे की ओर गिनते हैं, Python के ढंग से।

s <- "abcdefgh"
str_sub(s, 2, 4)
#> [1] "bcd"
str_sub(s, 5)
#> [1] "efgh"
str_sub(s, -3, -2)
#> [1] "fg"
str_sub(s, c(1, 4), c(2, 5))
#> [1] "ab" "de"
str_sub(s, c(1, 4, 6), c(2, 5, -1))
#> [1] "ab"  "de"  "fgh"

s |> str_sub(2, 4) # these functions are designed for pipes
#> [1] "bcd"
स्ट्रिंग जोड़ना

str_flatten एक अक्षर वेक्टर को एक अकेली स्ट्रिंग में बदल देता है। collapse आर्गुमेंट हर एलिमेंट के बीच डाला जाता है और इसका डिफ़ॉल्ट "" है।

c("R", "Julia", "Python") |> str_flatten()
#> [1] "RJuliaPython"
c("R", "Julia", "Python") |> str_flatten(collapse = " - ")
#> [1] "R - Julia - Python"

str_c कई अक्षर वेक्टर को एक अकेले अक्षर वेक्टर में बदलता है, और ज़रूरत पड़ने पर रीसाइक्लिंग करता है।

str_c(LETTERS[1:8], 1:8, sep = ":")
#> [1] "A:1" "B:2" "C:3" "D:4" "E:5" "F:6" "G:7" "H:8"

str_glue R में आसान स्ट्रिंग इंटरपोलेशन लाता है। ब्रेसिज़ { } के अंदर के एक्सप्रेशन को समझा जाता है और उसका टेक्स्ट रूप डाल दिया जाता है।

r <- 5.3
pi <- 3.14159
str_glue("A circle of radius {r} has area {pi * r^2}")
A circle of radius 5.3 has area 88.2472631
स्ट्रिंग को बाँटना

R का बहुत आम इस्तेमाल बिखरे हुए डेटा को विश्लेषण के लिए एक एकरूप रूप में ढालना है। इसमें मदद के लिए टेक्स्ट को सबस्ट्रिंग में बाँटने के कई तरीके हैं। ज़्यादातर अभी के दायरे से बाहर हैं।

str_split_1 सबसे आसान है, जो एक अकेली स्ट्रिंग को किसी तय पैटर्न पर बाँटकर टुकड़ों के वेक्टर में बदल देता है (इसका कोई डिफ़ॉल्ट पैटर्न नहीं है)।

s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R"      "Julia"  "Python"
स्ट्रिंग बदलना

कुछ भाषाएँ (मुख्यतः यूरोपीय) बड़े अक्षरों और छोटे अक्षरों में अंतर करती हैं। इन्हें आपस में बदलने के लिए stringr में कई फंक्शन हैं, जो लोकेल के हिसाब से सही तरीके से काम करते हैं:

  • str_to_lower()
  • str_to_upper()
  • str_to_title() : हर शब्द का पहला अक्षर बड़ा
  • str_to_sentence() : वाक्य का पहला अक्षर बड़ा
str_to_upper("elixir")    # defaults to locale = "en"
#> [1] "ELIXIR"
str_to_upper("ελληνικά")  # infers Greek
#> [1] "ΕΛΛΗΝΙΚΆ"

str_to_title("the cat sat on the mat")
#> [1] "The Cat Sat On The Mat"
str_to_sentence("the cat sat on the mat")
#> [1] "The cat sat on the mat"

पैटर्न मिलान के आधार पर सबस्ट्रिंग बदलने के लिए, str_replace() पैटर्न की पहली बार आई जगह बदलता है, str_replace_all() सारी जगह बदलता है।

अक्षर इंडेक्सिंग के आधार पर सबस्ट्रिंग बदलने के लिए str_sub() का असाइनमेंट रूप मौजूद है।

 s <- "abcde"
str_sub(s, 3, 4) <- "yz"
s
#> [1] "abyze"

निर्देश

इस अभ्यास में आप लॉग लाइनों पर काम करेंगे।

हर लॉग लाइन एक स्ट्रिंग होती है, जो इस तरह बनी होती है: "[<LEVEL>]: <MESSAGE>"।

लॉग लेवल तीन तरह के होते हैं:

  • INFO
  • WARNING
  • ERROR

आपके पास तीन काम हैं। हर काम में एक लॉग लाइन दी जाएगी और आपको उसके साथ कुछ करना होगा।

आप चाहें तो base R के पुराने फंक्शन इस्तेमाल कर सकते हैं, चाहें तो stringr लाइब्रेरी। दोनों से छोटे और व्यावहारिक हल मिल सकते हैं।

1. लॉग लाइन से मैसेज निकालिए

लॉग लाइन का मैसेज लौटाने के लिए message फंक्शन बनाइए:

message("[ERROR]: Invalid operation")
#> "Invalid operation"

शुरू या अंत में पड़ी कोई भी खाली जगह हटा देनी चाहिए:

message("[WARNING]:  Disk almost full\r\n")
#> "Disk almost full"

2. लॉग लाइन से लॉग लेवल निकालिए

लॉग लाइन का लॉग लेवल लौटाने के लिए log_level फंक्शन बनाइए। यह लेवल छोटे अक्षरों में लौटाया जाना चाहिए:

log_level("[ERROR]: Invalid operation")
#> "error"

3. लॉग लाइन को नए रूप में लिखिए

ऐसा reformat फंक्शन बनाइए जो लॉग लाइन को नए रूप में लिखे: पहले मैसेज आए और उसके बाद कोष्ठकों में लॉग लेवल:

reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
R Exercism

लॉग लेवल शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और R को 21 कॉन्सेप्ट111 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।