2012-01-05 14 views
17

Sadece Haskell'i kullanarak baktım ve farkettim (anlayabildiğim kadarıyla), daha küçük bir dizginin içerip içermediğini görmek için bir dizgiyi kontrol etmenin doğrudan bir yolu yoktur. Bu yüzden sadece bir atış yapacağımı düşündüm. Temelde fikir, iki dizenin aynı büyüklükte olup olmadığını ve eşit olup olmadığını kontrol etmekti. Kontrol edilen dizge daha uzunsa, kafaya tekrar tekrar sarılır ve kontrol edilen dizge aynı uzunlukta oluncaya kadar tekrar kontrol edilir."Dize X içeriyor" yöntemini yazmanın daha iyi bir yolu var mı?

Diğer olasılıkları kullanabilmek için desen eşleştirmesi kullandım.

stringExists "" wordToCheckAgainst = False 
stringExists wordToCheckFor "" = False 
stringExists wordToCheckFor wordToCheckAgainst | length wordToCheckAgainst < length wordToCheckFor = False 
               | length wordToCheckAgainst == length wordToCheckFor = wordToCheckAgainst == wordToCheckFor 
               | take (length wordToCheckFor) wordToCheckAgainst == wordToCheckFor = True 
               | otherwise = stringExists wordToCheckFor (tail wordToCheckAgainst) 

cevap

41

Eğer Hoogle kontrol ettin: Bu benim ile geldi nedir?

Aradığınız işlevin imzasını ararsanız (String -> String -> Bool) en iyi sonuçları isInfixOf görmeniz gerekir. Data.List den

+1

+1. Tüm Haskell kodlayıcılarının en iyi arkadaşı :) – Daenyth

+17

[isInfixOf' kaynağının incelenmesi] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/Data-List.html #isInfixOf) öğreticidir. – dave4420

+0

@ dave4420 Bağlantı bozuk. – ThreeFx

23

isInfixOf mutlaka ancak uzun haystacks veya perverse¹ iğnelerin durumda çok daha iyi bir ortalama ve en kötü durum karmaşıklığı ile daha gelişmiş string matching algorithms düşünmelisiniz, sorunu çözecektir.


sadece a oluşan gerçekten uzun bir dize 's ve bir a sürü ile bir iğne' ucunda başında s ve biri b düşünün ¹.

+0

Daha etkin bir algoritmanın 'String' (veya' [a] ') 'dan farklı bir veri yapısı gerektirdiğini unutmayın. –

+3

Gerçekten de, genellikle giriş dizisinin ön işlemlerinin önceden yapılması gerekir. Bunları bir '(String -> String -> Bool) işleviyle sonuçlanacak şekilde uygulamak kesinlikle mümkündür. – Jan

+0

Performansla gerçekten ilgileniyorsanız, muhtemelen şu şekilde uygularsınız: [Data.Text.Search.indices] (http://hackage.haskell.org/packages/archive/text/latest/doc/html /src/Data-Text-Search.html#indices) (Not 'Data.Text.isInfixOf', bu bağlamda uygulanır; tembellik nedeniyle, ilk dizin bulunduğundan sonra durabilir) –

9

Metin işleme gereksinimleriniz için text package (Hrugge, şimdi de Haskell Platform'un bir parçası olan text) kullanmayı düşünün. Yerleşik liste tabanlı String'dan daha fazla zaman ve alan verimli olan bir Unicode metin türü sağlar. Dize araması için, Data.List.isInfixOf tarafından kullanılan naif yönteminden daha iyi bir karmaşıklığa sahip olan(implements) bir Boyer-Moore-based algorithm paketi.

Kullanım örneği: Hoogle için

Prelude> :s -XOverloadedStrings 
Prelude> import qualified Data.Text as T 
Prelude Data.Text> T.breakOnAll "abc" "defabcged" 
[("def","abcged")] 
Prelude Data.Text> T.isInfixOf "abc" "defabcged" 
True 
+0

Yalnızca, alt dizini denetlemek için OverloadedStrings gerekli maçlar olsa da oldukça kötü bir siğildir. 'Pack' ve' unpack''de sarmak zorunda kalmanın alternatifi de gerçekten tatmin edici değil. – ely

İlgili konular