Riješeno: provjerite je li popis sortiran

Naravno, ilustrirat ću proces provjere je li lista u Haskellu sortirana ili ne. Ovo je uobičajena operacija u funkcionalnom programiranju i omogućuje nam da osiguramo da elementi na popisu slijede određeni redoslijed, često od najmanjeg prema najvećem (ili obrnuto).

Haskell, budući da je statički tipiziran, čisto funkcionalni programski jezik, pruža nam različite načine za rješavanje ovog problema. Dobro je poznat po snažnom zaključivanju tipa, što će nam značajno pomoći u ovom zadatku.

##

Problem: Provjera je li popis sortiran

Kao Haskell programer, od vas se često traži da osigurate da sadržaj popisa slijedi sortirani redoslijed. To znači da su elementi raspoređeni uzlaznim ili silaznim redoslijedom. Ovo je čest zadatak koji se javlja kada se radi o korisničkim unosima, čitanju datoteka ili upravljanju podacima općenito.

Najjednostavniji način da provjerite je li popis sortiran u Haskell-u je usporedbom s njegovom sortiranom verzijom. Haskell nudi ugrađenu funkciju, sort, koju možemo koristiti za sortiranje popisa uzlaznim redoslijedom. Ako popis nakon sortiranja ostane isti, možemo sa sigurnošću zaključiti da je već sortiran. Pogledajmo kako to možemo učiniti:

import Data.List
isSorted :: (Ord a) => [a] -> Bool
isSorted xs = xs == sort xs

No, ova metoda nije optimalna jer zahtijeva potpuno sortiranje popisa što troši vrijeme i resurse, posebno za velike popise.

##

Rješenje: optimizirani kod

Lista je sortirana ako je za svaki par susjednih elemenata prvi manji ili jednak drugom. Da bismo to implementirali, koristit ćemo zipWith i sve funkcije u kombinaciji. Evo optimiziranog koda:

isSorted :: (Ord a) => [a] -> Bool
isSorted xs = sve (uncurry (<=)) (zip xs (rep xs)) [/code] zip kombinira dvije liste u listu parova, dok rep preskače prvi element i vraća ostatak. uncurry primjenjuje binarni operator na par, i all provjerava da li uvjet vrijedi za sve elemente na popisu. U našem slučaju uvjet je da za svaki par prvi element bude niži ili jednak drugom.

##

Korak po korak objašnjenje koda

Optimizirani kod možemo dalje razumjeti tako da ga podijelimo u korake. Ideja je sekvencijalno provjeriti svaki par elemenata na popisu, a ako nađemo bilo koji par u kojem je prvi element veći od drugog, vraćamo False jer popis nije sortiran.

1. zip xs (rep xs) će uzeti popis [1,2,3,4] i pretvoriti ga u popis parova [(1,2),(2,3),(3,4)]. Svaki par je u osnovi trenutni element i sljedeći element na popisu.

2. Zatim koristimo svi funkcija koja uzima predikat (funkcija koja vraća Bool) i popis i vraća True samo ako je predikat istinit za sve elemente na popisu.

3. Naš predikat ovdje je (bez curryja (<=)). uncurry uzima funkciju i torku i primjenjuje funkciju na elemente torke. <= je ovdje naša funkcija, tako da bi uncurry (<=) bila funkcija koja uzima torku (a, b) i vraća True ako je a <= b. Ovaj nam pristup pomaže učinkovito riješiti problem u linearnom vremenu, pružajući robusno i učinkovito rješenje kada se radi s potencijalno velikim popisima. Što se tiče stila u Haskell-u, jezik promovira pisanje čistog i sažetog koda. Stoga je dobar stil podijeliti i apstrahirati svoj kod u male funkcije koje se mogu sastaviti i razumne dijelove. Haskell visoko cijeni što vam omogućuje pisanje lijepog, jasnog koda visoke razine.

Povezani postovi:

Ostavite komentar