Trilhas
/
R
R
/
Exercícios
/
Níveis de log
Níveis de log

Níveis de log

Exercício de aprendizagem

Introdução

Contexto

Uma string é um pedaço de texto entre aspas. Qualquer versão do R com suporte atualmente codifica strings em UTF-8, então a maioria dos idiomas do mundo pode ser usada.

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

Infelizmente, a terminologia pode confundir quem já programa em outras linguagens.

Embora o type seja character, o R não faz distinção entre uma única letra (chamada char em várias outras linguagens, mas não no R) e uma string longa. Ambas são um único item e podem estar entre aspas simples ' ' ou duplas " " de forma intercambiável.

O guia de estilo recomenda usar aspas duplas, exceto quando você quer usar aspas duplas dentro da string sem escapá-las.

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

Um character vector é, portanto, um vetor de strings, com cada string como um único elemento.

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

No exemplo acima, length(s[1]) é equivalente a length("some"): o número de elementos do vetor, não o comprimento da string.

Manipular uma string individual é obviamente possível, como com nchar() no exemplo acima, mas exige funções específicas que serão discutidas abaixo.

Funções para strings

Quase tudo é possível no R base, mas muitos programadores acham o suporte à manipulação de strings bastante limitado e confuso.

Felizmente, existem pacotes do tidyverse que são muito mais intuitivos, flexíveis e coerentes.

R base

Ainda existe muito código legado usando funções de string do estilo antigo. Isso inclui a maioria das soluções da comunidade no Exercism.

Além disso, para tarefas pequenas pode ser útil usar funções nativas em vez de importar uma biblioteca grande. Os mantenedores da trilha de R tendem a adotar essa abordagem ao escrever soluções exemplares para validar os exercícios.

Portanto, ainda vale a pena aprender um pouco sobre as abordagens antigas.

nchar

Retorna o número de caracteres em uma string.

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

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

O tópico (complicado!) do que "caractere" significa está além do nosso escopo. Apenas observe alguns pontos nos exemplos acima:

  • Embora implementadas em C internamente, as strings no R não são terminadas em \0 (o que adicionaria 1 ao comprimento).
  • Caracteres Unicode de vários bytes são tratados como você esperaria ou torceria. "Hrōðgār" tem 7 caracteres (também chamados de "runas" ou "pontos de código"), mas precisa de 10 bytes para armazenamento.
paste e paste0

Combina um número arbitrário de strings em uma única string.

Opcionalmente, um separador pode ser especificado para paste: o padrão é um espaço.

paste0(v) é equivalente a paste(v, sep = "").

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

Para um controle mais fino sobre a montagem de strings, o R copia a função sprintf do C (e de várias linguagens posteriores: a Wikipedia lista cerca de 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

Espaços em branco no início e/ou no fim podem ser removidos com trimws():

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

Existe um parâmetro which = "left" (ou "right") para evitar remover as duas pontas.

substr

Opera sobre uma única string e retorna uma substring entre dois limites (inclusive).

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

Divide uma string em uma lista do R, com base em uma string separadora. O separador é obrigatório (sem valor padrão), mas pode ser uma string vazia.

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

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

Listas serão abordadas em um conceito separado. Se você ainda não chegou a essa parte do programa, saiba por enquanto que a função unlist() vai (neste caso) converter uma lista em um vetor.

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

Tidyverse

Sendo generosos, poderíamos dizer que as funções de string do estilo antigo não são o melhor que o R tem a oferecer (visões menos generosas são possíveis).

Para melhorar a situação, a biblioteca stringr está em desenvolvimento desde 2009 e agora é uma parte fundamental da coleção Tidyverse.

Importe-a para o seu namespace com library(stringr) ou library(tidyverse).

Alguns recursos principais incluem:

  • Todos os nomes de funções têm o prefixo str_ e tentam deixar o propósito claro.
  • A ordem dos argumentos tenta ser coerente, com os dados de entrada como primeiro argumento.
  • As entradas podem ir de uma única string a estruturas de dados complexas. As funções tentam se adaptar e fazer o que faz mais sentido.

Como todos os pacotes do Tidyverse, o stringr tem boa documentação, normalmente escrita pelo(s) autor(es) do pacote.

Digressão: um resumo rápido sobre pipes

O uso de pipes |> para conectar funções será discutido com mais detalhes em outras partes do programa.

Por enquanto, é útil saber que:

  • Um resultado à esquerda do pipe se torna o primeiro argumento da função à direita (aqui, "à direita" ignora quebras de linha opcionais).
  • Quaisquer argumentos restantes podem ser incluídos na chamada da função.
  • No R, precisamos encadear o pipe para uma chamada de função, não apenas um nome, então os parênteses são sempre obrigatórios (isso é diferente de algumas outras linguagens).

O exemplo abaixo ilustra a sintaxe. As funções individuais serão discutidas mais adiante.

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"
Gerenciar comprimentos

str_length conta pontos de código (semelhante a nchars).

Várias outras funções manipulam espaços em branco, incluindo str_trim() e str_squish(). Muitas vezes essa é uma tarefa de limpeza essencial no início de qualquer projeto de ciência de dados.

# 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"
Selecionar partes de strings

A função str_sub(string, start, end) retorna a substring de start até end (inclusive), enquanto str_sub_all() pode operar sobre várias strings.

Há muita flexibilidade. start e end têm como padrão o primeiro e o último caractere, respectivamente. Eles podem ser vetores de índices. Em um contraste bem-vindo com a indexação de vetores, valores negativos contam a partir do fim da string, no estilo do 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"
Juntar strings

str_flatten converte um vetor de caracteres em uma única string. O argumento collapse é inserido entre cada elemento e tem como padrão "".

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

str_c converte vários vetores de caracteres em um único vetor de caracteres, com reciclagem conforme necessário.

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 traz interpolação de strings simples para o R. Expressões dentro das chaves { } são interpretadas e a representação em texto é substituída.

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
Dividir strings

Um uso muito comum do R é transformar dados bagunçados em um formato consistente para análise. Para ajudar nisso, existem várias maneiras de dividir texto em substrings. A maioria está além do escopo atual.

str_split_1 é a mais simples, convertendo uma única string em um vetor de partes, divididas em algum padrão especificado (não há padrão predefinido).

s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R"      "Julia"  "Python"
Transformar strings

Algumas linguagens (principalmente europeias) distinguem entre letras MAIÚSCULAS e minúsculas. Há um conjunto de funções do stringr para converter entre elas, de formas adequadas ao locale:

  • str_to_lower()
  • str_to_upper()
  • str_to_title() : primeira letra de cada palavra em maiúscula
  • str_to_sentence() : primeira letra da frase em maiúscula
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"

Para substituição de substring com base em correspondência de padrões, str_replace() altera a primeira ocorrência do padrão e str_replace_all() altera todas as ocorrências.

Para substituição de substring com base na indexação por caractere, existe uma forma de atribuição de str_sub().

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

Instruções

Neste exercício você vai processar linhas de log.

Cada linha de log é uma string formatada assim: "[<LEVEL>]: <MESSAGE>".

Existem três níveis de log diferentes:

  • INFO
  • WARNING
  • ERROR

Você tem três tarefas, e cada uma recebe uma linha de log e pede que você faça algo com ela.

Fique à vontade para usar tanto funções legadas do R base quanto a biblioteca stringr, e as duas permitem soluções curtas e viáveis.

1. Extrair a mensagem de uma linha de log

Implemente a função message para retornar a mensagem de uma linha de log:

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

Qualquer espaço em branco no início ou no fim deve ser removido:

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

2. Extrair o nível de log de uma linha de log

Implemente a função log_level para retornar o nível de log de uma linha de log, que deve ser retornado em letras minúsculas:

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

3. Reformatar uma linha de log

Implemente a função reformat, que reformata a linha de log, colocando a mensagem primeiro e o nível de log depois dela, entre parênteses:

reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
Editar via GitHub O link abre em uma nova janela ou aba
R Exercism

Tudo pronto para começar Níveis de log?

Crie sua conta no Exercism para aprender e dominar R com 21 conceitos111 exercícios e mentoria humana de verdade, tudo de graça.