Ratkaistu: tarkista, onko lista järjestetty

Viimeisin päivitys: 09/11/2023

Toki havainnollistan prosessia, jolla tarkistetaan, onko Haskellin luettelo lajiteltu vai ei. Tämä on yleinen operaatio toiminnallisessa ohjelmoinnissa ja sen avulla voimme varmistaa, että listan elementit noudattavat tiettyä järjestystä, usein pienimmästä suurimpaan (tai päinvastoin).

Haskell, joka on staattisesti kirjoitettu, puhtaasti toiminnallinen ohjelmointikieli, tarjoaa meille erilaisia ​​tapoja ratkaista tämä ongelma. Se on tunnettu vahvasta tyyppipäätelmästään, joka auttaa meitä merkittävästi tässä tehtävässä.

##

Ongelma: Tarkistaa, onko luettelo lajiteltu

Haskell-kehittäjänä sinun on usein varmistettava, että luettelon sisältö noudattaa lajiteltua järjestystä. Tämä tarkoittaa, että elementit on järjestetty joko nousevaan tai laskevaan järjestykseen. Tämä on yleinen tehtävä, joka syntyy, kun käsitellään käyttäjän syötteitä, luetaan tiedostoja tai hallitaan tietoja yleensä.

Yksinkertaisin tapa tarkistaa, onko luettelo lajiteltu Haskellissa, on verrata sitä sen lajiteltuun versioon. Haskell tarjoaa sisäänrakennetun toiminnon, lajittelun, jonka avulla voimme lajitella luettelon nousevaan järjestykseen. Jos lista pysyy samana lajittelun jälkeen, voimme turvallisesti päätellä, että se oli jo lajiteltu. Katsotaan kuinka voimme tehdä tämän:

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

Mutta tämä menetelmä ei ole optimaalinen, koska se vaatii täydellisen luettelon, mikä kuluttaa aikaa ja resursseja erityisesti suurille listoille.

##

Ratkaisu: Optimoitu koodi

Lista lajitellaan, jos jokaisen vierekkäisen elementin parin ensimmäinen on pienempi tai yhtä suuri kuin toinen. Tämän toteuttamiseksi käytämme zipWithiä ja kaikkia toimintoja yhdessä. Tässä on optimoitu koodi:

isSorted :: (Järjestys a) => [a] -> Bool
isSorted xs = kaikki (uncurry (<=)) (zip xs (tail xs)) [/code] vetoketju yhdistää kaksi luetteloa pariluetteloksi, while pyrstö ohittaa ensimmäisen elementin ja palauttaa loput. uncurry käyttää binäärioperaattoria pariin ja kaikki tarkistaa, päteekö ehto kaikille luettelon elementeille. Meidän tapauksessamme ehto on, että kunkin parin ensimmäisen elementin tulee olla pienempi tai yhtä suuri kuin toinen.

##

Koodin vaiheittainen selitys

Voimme ymmärtää optimoidun koodin paremmin jakamalla sen vaiheisiin. Ajatuksena on tarkistaa listan jokainen elementtipari peräkkäin, ja jos löydämme parin, jossa ensimmäinen elementti on suurempi kuin toinen, palautetaan False, koska luetteloa ei ole lajiteltu.

1. vetoketju xs (häntä xs) ottaa luettelon [1,2,3,4] ja muuntaa sen pariluetteloksi [(1,2),(2,3),(3,4)]. Jokainen pari on periaatteessa nykyinen elementti ja seuraava elementti luettelossa.

2. Käytämme sitten kaikki funktio, joka ottaa vastaan ​​predikaatin (funktio, joka palauttaa Boolin) ja listan ja palauttaa True vain, jos predikaatti on tosi kaikille listan elementeille.

3. Predikaattimme tässä on (riippumaton (<=)). uncurry ottaa funktion ja monikon ja soveltaa funktiota monikon elementteihin. <= on funktiomme tässä, joten uncurry (<=) olisi funktio, joka ottaa monikon (a, b) ja palauttaa True, jos a <= b. Tämä lähestymistapa auttaa meitä ratkaisemaan ongelman tehokkaasti lineaarisessa ajassa, mikä tarjoaa vankan ja tehokkaan ratkaisun käsiteltäessä mahdollisesti suuria listoja. Mitä tulee Haskellin tyyliin, kieli edistää puhtaan ja tiiviin koodin kirjoittamista. Joten on hyvä tapa jakaa ja abstraktoida koodi pieniksi, koostettaviksi funktioiksi ja järkeviin osiin. Haskell arvostaa suuresti, että sen avulla voit kirjoittaa kaunista, selkeää ja korkeatasoista koodia.

Related viestiä: