Regular expression (regex) adalah alat yang sangat ampuh untuk memanipulasi dan mengekstrak pola dari teks. Dalam Python, modul re
menyediakan fungsionalitas untuk bekerja dengan regex. Salah satu tugas umum adalah mencocokkan angka, dan dalam banyak kasus, kita hanya tertarik pada angka bulat (yaitu, angka yang tidak mengandung titik desimal). Artikel ini akan membahas secara mendalam berbagai cara untuk mencapai hal ini menggunakan regex di Python, termasuk pertimbangan tentang kasus tepi dan optimasi.
Pendahuluan: Mengapa Regex untuk Angka Bulat?
Mungkin Anda bertanya, mengapa kita perlu regex untuk mencocokkan angka bulat? Bukankah kita bisa menggunakan fungsi int()
? Meskipun int()
berfungsi untuk mengonversi string menjadi integer, regex memberikan fleksibilitas dan kontrol yang lebih besar, terutama ketika:
- Angka tertanam dalam teks: Regex memungkinkan kita mengekstrak angka dari string yang lebih panjang yang mengandung karakter lain.
- Validasi format: Kita dapat memastikan bahwa string hanya mengandung angka dan karakter opsional seperti tanda plus atau minus di depan.
- Pola kompleks: Regex dapat digunakan untuk mencocokkan pola angka yang lebih kompleks, seperti angka dengan panjang tertentu atau angka yang berada dalam rentang tertentu.
- Efisiensi: Dalam beberapa kasus, regex dapat lebih efisien daripada kombinasi fungsi string dan konversi tipe data.
Dasar-Dasar Regex untuk Angka
Sebelum kita menyelam lebih dalam, mari kita tinjau beberapa elemen dasar regex yang akan kita gunakan:
\d
: Mencocokkan digit (0-9).+
: Mencocokkan satu atau lebih kemunculan karakter sebelumnya.*
: Mencocokkan nol atau lebih kemunculan karakter sebelumnya.?
: Mencocokkan nol atau satu kemunculan karakter sebelumnya.^
: Mencocokkan awal string.$
: Mencocokkan akhir string.[]
: Mendefinisikan kelas karakter. Misalnya,[0-5]
mencocokkan digit antara 0 dan 5.()
: Membuat grup penangkap. Ini memungkinkan kita untuk mengekstrak bagian tertentu dari string yang cocok.|
: Operator "atau". Misalnya,a|b
mencocokkan "a" atau "b".\b
: Word boundary. Mencocokkan batas antara karakter word (\w) dan non-word (\W). Ini berguna untuk memastikan kita mencocokkan angka sebagai unit terpisah, bukan sebagai bagian dari kata yang lebih panjang.\-
: Mencocokkan karakter minus. Perlu di-escape karena minus memiliki arti khusus di dalam character class ([]
).
Contoh Sederhana: Mencocokkan Angka Positif
Regex paling sederhana untuk mencocokkan angka positif tanpa titik desimal adalah \d+
. Ini berarti "satu atau lebih digit".
import re pattern = r"\d+" text = "Ada 123 apel dan 456 pisang." matches = re.findall(pattern, text) print(matches) # Output: ['123', '456']
Dalam contoh ini, re.findall()
mengembalikan daftar semua string yang cocok dengan pola \d+
dalam teks.
Mencocokkan Angka Bulat dengan Tanda Opsional
Sekarang, mari kita tingkatkan kompleksitas. Bagaimana jika kita ingin mencocokkan angka yang mungkin memiliki tanda plus atau minus di depannya? Kita dapat menggunakan karakter +
dan -
di dalam character class []
, dan membuatnya opsional dengan menggunakan ?
.
import re pattern = r"[+-]?\d+" text = "Suhu hari ini adalah +25 derajat, kemarin -5 derajat, dan lusa 30 derajat." matches = re.findall(pattern, text) print(matches) # Output: ['+25', '-5', '30']
Di sini, [+-]?
berarti "nol atau satu kemunculan karakter plus atau minus".
Kasus Tepi dan Pertimbangan Tambahan
Penting untuk mempertimbangkan kasus tepi ketika membuat regex. Berikut beberapa hal yang perlu diingat:
- Spasi di depan atau belakang: Jika Anda ingin memastikan bahwa angka tidak memiliki spasi di depan atau belakang, Anda dapat menggunakan
\b
(word boundary) atau^
dan$
. - Angka dengan leading zeros: Jika Anda ingin mengizinkan atau melarang angka dengan leading zeros (misalnya, "007"), Anda perlu menyesuaikan regex Anda.
- Angka dalam format tertentu: Jika angka harus dalam format tertentu (misalnya, panjang tertentu), Anda dapat menggunakan quantifier seperti
{n}
(tepat n kali) atau{n,m}
(antara n dan m kali). - Karakter selain angka: Pastikan regex Anda tidak mencocokkan string yang mengandung karakter selain angka (misalnya, "123a"). Word boundary (
\b
) sangat membantu di sini.
Contoh: Validasi Input Angka Bulat
Misalkan Anda ingin membuat fungsi yang memvalidasi apakah sebuah string adalah angka bulat yang valid. Anda dapat menggunakan regex untuk melakukan hal ini.
import re def is_integer(string): """Memeriksa apakah string adalah angka bulat yang valid.""" pattern = r"^[+-]?\d+$" # ^ dan $ memastikan seluruh string cocok match = re.match(pattern, string) return bool(match) print(is_integer("123")) # Output: True print(is_integer("-45")) # Output: True print(is_integer("+6")) # Output: True print(is_integer("007")) # Output: True (leading zeros diizinkan) print(is_integer("12.3")) # Output: False print(is_integer("abc")) # Output: False print(is_integer("123 ")) # Output: False (ada spasi di belakang)
Dalam contoh ini, re.match()
digunakan untuk memeriksa apakah pola cocok dengan awal string. Kita menggunakan ^
dan $
untuk memastikan bahwa seluruh string harus cocok dengan pola, bukan hanya sebagian.
Mencocokkan Angka Bulat dalam Teks yang Lebih Kompleks
Seringkali, kita perlu mencocokkan angka bulat dalam teks yang lebih kompleks, di mana angka-angka tersebut mungkin dikelilingi oleh karakter lain. Dalam kasus ini, word boundary (\b
) sangat berguna.
import re text = "Harga barang ini adalah $123, dan beratnya 45kg. Kode produk adalah ABC123XYZ." pattern = r"\b[+-]?\d+\b" # Word boundary di kedua sisi matches = re.findall(pattern, text) print(matches) # Output: ['123', '45']
Perhatikan bahwa "123" dalam "ABC123XYZ" tidak cocok karena \b
memerlukan batas antara karakter word (huruf, angka, atau underscore) dan karakter non-word.
Menangani Leading Zeros dengan Lebih Hati-hati
Regex di atas mengizinkan angka dengan leading zeros. Jika kita ingin melarangnya (kecuali angka nol itu sendiri), kita perlu regex yang lebih kompleks.
import re def is_integer_no_leading_zeros(string): """Memeriksa apakah string adalah angka bulat tanpa leading zeros (kecuali 0).""" pattern = r"^(0|[+-]?[1-9]\d*)$" match = re.match(pattern, string) return bool(match) print(is_integer_no_leading_zeros("0")) # Output: True print(is_integer_no_leading_zeros("123")) # Output: True print(is_integer_no_leading_zeros("-45")) # Output: True print(is_integer_no_leading_zeros("007")) # Output: False print(is_integer_no_leading_zeros("+05")) # Output: False print(is_integer_no_leading_zeros("12.3")) # Output: False
Regex ini bekerja sebagai berikut:
^
: Mencocokkan awal string.(0|[+-]?[1-9]\d*)
: Ini adalah grup yang mencocokkan salah satu dari dua kemungkinan:0
: Angka nol.[+-]?[1-9]\d*
: Angka dengan tanda opsional ([+-]?
), diikuti oleh digit non-nol ([1-9]
), diikuti oleh nol atau lebih digit (\d*
).
$
: Mencocokkan akhir string.
Perbandingan Kinerja Regex vs. Metode Lain
Meskipun regex sangat fleksibel, penting untuk mempertimbangkan kinerjanya dibandingkan dengan metode lain, terutama ketika memproses data dalam jumlah besar. Dalam beberapa kasus, menggunakan kombinasi fungsi string dan konversi tipe data mungkin lebih efisien. Namun, pengukuran kinerja yang akurat sangat penting sebelum membuat keputusan.
Studi Kasus: Memproses Log File
Misalkan kita memiliki log file yang mengandung berbagai informasi, termasuk angka-angka bulat yang perlu kita ekstrak. Kita akan membandingkan kinerja regex dengan pendekatan berbasis fungsi string.
Pendekatan 1: Regex
import re import time def extract_integers_regex(log_file): """Mengekstrak angka bulat dari log file menggunakan regex.""" integers = [] pattern = r"\b\d+\b" with open(log_file, "r") as f: for line in f: matches = re.findall(pattern, line) integers.extend(matches) return integers # Contoh penggunaan (buat file log dummy terlebih dahulu) # with open("dummy_log.txt", "w") as f: # for i in range(10000): # f.write(f"Log entry {i}: Value = {i*2}, Error code = {i%10}\n") start_time = time.time() integers_regex = extract_integers_regex("dummy_log.txt") end_time = time.time() regex_time = end_time - start_time print(f"Waktu eksekusi menggunakan Regex: {regex_time:.4f} detik")
Pendekatan 2: Fungsi String dan Konversi Tipe Data
def extract_integers_string(log_file): """Mengekstrak angka bulat dari log file menggunakan fungsi string.""" integers = [] with open(log_file, "r") as f: for line in f: words = line.split() for word in words: try: integer = int(word) integers.append(integer) except ValueError: pass # Bukan angka bulat return integers start_time = time.time() integers_string = extract_integers_string("dummy_log.txt") end_time = time.time() string_time = end_time - start_time print(f"Waktu eksekusi menggunakan Fungsi String: {string_time:.4f} detik")
Analisis Kinerja:
Setelah menjalankan kedua fungsi di atas pada file log dummy (misalnya, dummy_log.txt
dengan 10.000 baris), Anda akan melihat bahwa kinerja kedua pendekatan tersebut bisa sangat bervariasi tergantung pada karakteristik data. Secara umum:
- Regex: Cenderung lebih lambat untuk file log yang sangat sederhana dengan sedikit variasi. Overhead kompilasi regex dan pencarian pola dapat menjadi signifikan.
- Fungsi String: Mungkin lebih cepat untuk file log sederhana karena overhead lebih rendah. Namun, performanya dapat menurun jika file log mengandung banyak kata yang bukan angka dan memerlukan banyak pengecualian
ValueError
.
Penting: Lakukan benchmark dengan data nyata Anda untuk menentukan pendekatan mana yang paling efisien untuk kasus penggunaan spesifik Anda. Faktor-faktor seperti ukuran file log, kompleksitas pola angka, dan jumlah "false positives" (kata-kata yang bukan angka tetapi perlu diperiksa) akan memengaruhi kinerja.
Data Tabel: Ringkasan Pola Regex dan Penggunaannya
Berikut adalah tabel yang merangkum beberapa pola regex yang telah kita bahas dan penggunaannya:
Pola Regex | Deskripsi | Contoh Penggunaan |
---|---|---|
\d+ |
Mencocokkan satu atau lebih digit (angka positif). | Mengekstrak semua angka positif dari sebuah string. |
[+-]?\d+ |
Mencocokkan angka dengan tanda plus atau minus opsional. | Mencocokkan suhu, perubahan nilai, dll. |
^[+-]?\d+$ |
Memvalidasi apakah sebuah string adalah angka bulat dengan tanda opsional. | Memvalidasi input pengguna. |
\b\d+\b |
Mencocokkan angka positif sebagai kata terpisah. | Mengekstrak ID produk, nomor seri, dll. |
\b[+-]?\d+\b |
Mencocokkan angka dengan tanda opsional sebagai kata terpisah. | Mengekstrak nilai moneter, skor, dll. |
`^(0 | [+-]?[1-9]\d*)$` | Memvalidasi angka bulat tanpa leading zeros (kecuali 0). |
Gaya Penulisan: Teknis, Serius
Tabel di atas disajikan dengan gaya teknis dan serius. Deskripsi singkat dan langsung, dan contoh penggunaan mengilustrasikan aplikasi praktis dari setiap pola regex. Tujuannya adalah untuk memberikan informasi yang jelas dan ringkas kepada pembaca yang memiliki pemahaman dasar tentang regex.
Kesimpulan
Mencocokkan angka bulat dengan regex di Python adalah tugas yang relatif mudah, tetapi penting untuk mempertimbangkan kasus tepi dan memilih pola regex yang tepat untuk kebutuhan spesifik Anda. Dengan memahami elemen dasar regex dan bagaimana menggabungkannya, Anda dapat membuat pola yang kuat dan fleksibel untuk mengekstrak dan memvalidasi angka bulat dalam berbagai konteks. Selalu ingat untuk menguji regex Anda secara menyeluruh dan mempertimbangkan kinerja dibandingkan dengan metode lain, terutama ketika memproses data dalam jumlah besar. Word boundary (\b
) adalah alat yang sangat berguna untuk memastikan bahwa Anda mencocokkan angka sebagai unit yang terpisah. Selain itu, pertimbangkan implikasi dari leading zeros dan sesuaikan regex Anda sesuai kebutuhan.