Перейти до основного вмісту

String в Elixir

Рядки (strings) — це послідовності символів у кодуванні UTF-8. В Elixir рядки закліченні в подвійні лапки та мають багато корисних функцій для маніпуляції.

Основи рядків

Рядки в Elixir — це послідовності знаків, закодовані в UTF-8:

# Прості рядки
name = "Іван"
message = "Привіт, світ!"

# Багаторядкові рядки
text = "Це перший рядок
Це другий рядок
Це третій рядок"

# Спеціальні символи
escaped = "Лінія 1\nЛінія 2\tТабуляція"
quote = "Він сказав \"Привіт!\""

# Довжина рядка (кількість символів)
String.length("Привіт")
# 6

# Визначення порожнього рядка
empty = ""
String.length(empty)
# 0

На відміну від списків символів (char lists), рядки у подвійних лапках — це бінарні значення UTF-8.

Рядки vs побайтові послідовності

В Elixir існує различниця між рядками та побайтовими послідовностями:


# Рядок (string) - подвійні лапки
string = "Hello"
byte_size(string)
# 5

# Список символів (charlist) - одинарні лапки
charlist = 'Hello'
# [72, 101, 108, 108, 111]

# Рядок в UTF-8 займає більше байтів
string_ua = "Привіт"
String.length(string_ua)      # 6 символів
byte_size(string_ua)          # 12 байтів (2 байти за символ)

# Конвертація
String.to_charlist("Hi")
# [72, 105]

List.to_string([72, 105])
# "Hi"

Інтерполяція

Інтерполяція дозволяє вставляти значення в рядки за допомогою #{}:

name = "Марія"
age = 25

# Проста інтерполяція
greeting = "Привіт, #{name}!"
# "Привіт, Марія!"

# Вирази в інтерполяції
message = "#{name} має #{age} років"
# "Марія має 25 років"

# Математичні операції
result = "Результат: #{5 + 3}"
# "Результат: 8"

# Виклики функцій
text = "Велику літеру: #{String.upcase("hello")}"
# "Велику літеру: HELLO"

# Без інтерполяції
no_interpolate = "Це #{} не буде замінено"
# Помилка! Потрібно значення

Конкатенація та манупуляція

# Конкатенація оператором <>>
hello = "Hello"
world = "World"
result = hello <> " " <> world
# "Hello World"

# Функція String.concat
String.concat(["a", "b", "c"])
# "abc"

# Отримання символу за індексом
String.at("Hello", 0)
# "H"

String.at("Hello", 10)
# nil (індекс поза межами)

# Нарізання рядка
String.slice("Hello World", 0..4)
# "Hello"

String.slice("Hello World", 6..-1)
# "World"

# Заміна
String.replace("Hello World", "World", "Elixir")
# "Hello Elixir"

String.replace("aaa", "a", "b")
# "bbb"

String.replace("aaa", "a", "b", global: false)
# "baa" (тільки перша)

Перетворення регістру

# Великі літери
String.upcase("hello")
# "HELLO"

String.upcase("привіт")
# "ПРИВІТ"

# Малі літери
String.downcase("HELLO")
# "hello"

String.downcase("ПРИВІТ")
# "привіт"

# Перша велика, решта малі
String.capitalize("hELLO")
# "Hello"

# Кожне слово з великої літери
Regex.replace(~r/(\A|\s)(\S)/, "hello world", "\\1\\U\\2")
# "Hello World"

Поділ та з'єднання

# Поділ рядка
String.split("apple,banana,cherry", ",")
# ["apple", "banana", "cherry"]

# Поділ з регулярним виразом
String.split("a1b2c3", ~r/\d/)
# ["a", "b", "c", ""]

# З'єднання списку рядків
Enum.join(["a", "b", "c"], "-")
# "a-b-c"

# Видалення розділювачів на кінцях
String.trim("  hello  ")
# "hello"

String.trim_leading("  hello  ")
# "hello  "

String.trim_trailing("  hello  ")
# "  hello"

String.trim("123abc123", "123")
# "abc"

Пошук та перевірка

# Перевірка наявності підрядка
String.contains?("Hello World", "World")
# true

# Пошук позиції підрядка
String.myers_difference("kitten", "sitting")
# [eq: "k", del: "itten", ins: "sitting"]

# Перевірка початку/кінця
String.starts_with?("Elixir", "Eli")
# true

String.ends_with?("Elixir", "xir")
# true

# Перевірка, чи рядок лише з букв/цифр
String.match?("123", ~r/^\d+$/)
# true

String.match?("abc123", ~r/^[a-z]+$/)
# false

Регулярні вирази

Для складного пошуку та заміни в рядках використовуються регулярні вирази:

# Обрання за регулярним виразом
Regex.match?(~r/\d+/, "abc123def")
# true

# Отримання матчів
Regex.scan(~r/\d+/, "a1b2c3")
# [["1"], ["2"], ["3"]]

# Заміна за регулярним виразом
Regex.replace(~r/\d/, "a1b2c3", "X")
# "aXbXcX"

# Розділ за регулярним виразом
Regex.split(~r/\s+/, "hello   world   test")
# ["hello", "world", "test"]

Практичні приклади

# Email валідація
validate_email = fn email ->
  Regex.match?(~r/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, email)
end

validate_email.("user@example.com")
# true

# Форматування телефонного номера
format_phone = fn phone ->
  phone
  |> String.replace(~r/\D/, "")
  |> String.slice(0..9)
  |> (fn n -> "(#{String.slice(n, 0..2)}) #{String.slice(n, 3..5)}-#{String.slice(n, 6..9)}" end).()
end

format_phone.("1234567890")
# "(123) 456-7890"

# Трансформація: camelCase до snake_case
camel_to_snake = fn str ->
  str
  |> String.replace(~r/([a-z])([A-Z])/, "\\1_\\2")
  |> String.downcase()
end

camel_to_snake.("firstName")
# "first_name"

# Видалення невидимих символів
clean_text = fn text ->
  text
  |> String.trim()
  |> String.replace(~r/\s+/, " ")
end

clean_text.("  hello    world  ")
# "hello world"

Кодування та символи

# Перетворення в код точки Unicode
String.to_charlist("A")
# [65]

String.codepoints("ABC")
# ["A", "B", "C"]

# Кодування в різні формати
Base.encode64("Hello")
# "SGVsbG8="

Base.decode64("SGVsbG8=")
# {:ok, "Hello"}

# UTF-8 кодування
string = "Привіт"
:unicode.characters_to_binary(string, :utf8)
# <<208, 159, 209, 128, 208, 184, 208, 178, 209, 150, 209, 130>>

Часто використовувані функції String

Функція Опис Приклад
length/1 Кількість символів String.length("Hi") → 2
upcase/1 Велика літера String.upcase("hello") → "HELLO"
downcase/1 Мала літера String.downcase("HELLO") → "hello"
trim/1 Видалити пробіли String.trim(" hi ") → "hi"
split/2 Поділити рядок String.split("a,b", ",") → ["a", "b"]
replace/3 Замінити підрядок String.replace("abc", "a", "x") → "xbc"
contains?/2 Перевірити наявність String.contains?("hello", "ell") → true
slice/2 Витягти частину String.slice("hello", 0..1) → "he"

StringIO для обробки потоків

# Читання з рядка як зіStream
{:ok, pid} = StringIO.open("Hello World")

IO.read(pid, :line)
# "Hello World"

# Запис у рядок
{:ok, pid} = StringIO.open("")

IO.write(pid, "Hello")
IO.write(pid, " ")
IO.write(pid, "World")

StringIO.contents(pid)
# {"Hello World", ""}

# Очистити та заново писати
StringIO.rewind(pid)
IO.write(pid, "New content")

Рядки незмінні в Elixir. Всі операції з ними повертають нові рядки.

Коментарі

Популярні публікації

Шпаргалка по базових командах PostgreSQL

1. Підключення до PostgreSQL через командний рядок: psql -h <host> -p <port> -U <username> -d <database> 2. Підключення до бази без параметрів (якщо користувач і база мають однакове ім’я): psql 3. Показати список усіх баз даних: \l 4. Підключитися до іншої бази даних: \c <database_name> 5. Показати список таблиць у поточній базі: \dt 6. Показати всі об'єкти (таблиці, індекси, секвенції): \d 7. Показати таблиці з усіх схем: \dt *.* 8. Переглянути структуру конкретної таблиці: \d <table_name> 9. Виконати SQL-запит (приклад): SELECT * FROM users; 10. Вийти з psql: \q 11. Створити нову базу даних: CREATE DATABASE mydb; 12. Створити нову таблицю: CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE ); 13. Додати новий запис: INSERT INTO users (name, email) VALUES ('Іван', 'ivan@example.com'); 14. Оновити дані в таблиці: UPDATE users SET name = 'Петро' WH...

Основи GLSL

Що таке GLSL? GLSL (OpenGL Shading Language) – мова програмування шейдерів для OpenGL. Використовується для написання vertex, fragment, geometry та інших шейдерів, що працюють на GPU. Оголошення версії #version 330 core Вказує версію GLSL. Наприклад, 330 core відповідає OpenGL 3.3. Вхідні та вихідні змінні layout(location=0) in vec3 aPos; layout(location=1) in vec3 aNormal; out vec3 FragPos; in – вхідні атрибути (vertex shader). out – вихідні змінні (vertex shader) або фінальний колір (fragment shader). Основні типи даних float, int, bool vec2, vec3, vec4 mat2, mat3, mat4 sampler2D (текстури) Тип Опис Приклади використання vec2 Двокомпонентний вектор з типом float. - Текстурні координати (UV) - 2D позиції - Швидкість у 2D vec3 Трикомпонентний вектор з типом float. - Координати позицій у 3D - Нормалі - Колір у форматі RGB vec4 Чотирикомпо...

Атоми в мові програмування Elixir

Атоми в Elixir Атоми є фундаментальною концепцією в Elixir , що відіграє ключову роль у створенні надійних та масштабованих систем. В Elixir це специфічний тип даних, який є константою , незмінною , ідентифікованою за своїм ім'ям . Отже, атом в Elixir — це іменована константа, що представляє себе. Уявіть, що ви даєте унікальне ім'я певній речі, і це ім'я завжди посилається саме на цю річ, і ніколи на щось інше. Наприклад, атом :ok завжди буде означати саме успішне завершення операції, а не якесь інше значення. Технічно, атоми є похідними від чисел . Кожен унікальний атом зберігається у таблиці атомів, і йому присвоюється унікальний цілочисельний ідентифікатор. Це робить їх надзвичайно ефективними для порівняння: замість порівняння рядків (що є повільною операцією), Elixir порівнює цілочисельні ідентифікатори. Переваги та особливості використання атомів Переваги атомів: Ефективність. Завдяки своєму числовому представленню, порівняння атомів є дуже швидким. Це осо...

Встановлення PostgreSQL на Ubuntu-сервер

Встановлення Оновлюємо пакети та встановлюємо PostgreSQL: sudo apt update sudo apt install -y postgresql postgresql-contrib Перевіряємо статус сервісу: sudo systemctl status postgresql Якщо PostgreSQL не запущений, запустимо його: sudo systemctl start postgresql sudo systemctl enable postgresql Налаштування безпеки Зміна пароля: sudo -u postgres psql У консолі PostgreSQL: ALTER USER postgres PASSWORD 'міцний_пароль'; \q \q - вихід з консолі. Список основних команд для роботи з PostgreSQL можна переглянути за посиланням. За замовчуванням PostgreSQL слухає localhost (127.0.0.1). Щоб дозволити доступ із зовнішніх машин, редагуємо конфігурацію: sudo nano /etc/postgresql/17/main/postgresql.conf (замість 17 вкажи версію PostgreSQL, яку встановлено) Шукаємо рядок: #listen_addresses = 'localhost' та замінюємо на listen_addresses = '*' Зберігаємо (Ctrl + X, Y, Enter). Тепер редагуємо pg_hba.conf: sudo nano /etc/postgresql/17/main/pg_hba.conf...

Прості типи даних в Elixir

Мова Elixir має низку простих (примітивних) типів даних, які часто використовуються в повсякденному програмуванні. Числа Elixir підтримує цілі (integer) та дійсні числа (float). # Цілі числа a = 42 b = -7 # Дійсні числа c = 3.14 d = -0.001 Булеві значення Elixir має два булевих значення: true та false . x = true y = false z = x and y # false Атоми Атоми — це константи з іменем, що починається з двокрапки. Вони широко використовуються, наприклад, для імен параметрів або станів. :ok :error :running :elixir_is_fun Рядки Рядки в Elixir — це двійкові дані з кодуванням UTF-8, оголошуються в подвійних лапках. name = "Pavlo" greeting = "Привіт, #{name}!" Nil Nil — це спеціальне значення, що позначає "відсутність значення". value = nil is_nil(value) # true Бінарні дані та байти Бінарні дані оголошуються в подвійних лапках або як бінарні літерали. string = "Привіт" # це рядок, але також бінарні дані binary = ...