2009-05-04 15 views
6

मेरे पास दो स्ट्रिंग्स हैं जो हास्केल फ़ंक्शन के लिए तर्क के रूप में दिए गए हैं।हास्केल में एक स्ट्रिंग दूसरे से छोटा है या नहीं, यह जांचने के लिए कैसे करें?

s1s2 से छोटी है अगर s1 से कम s2 है या वे एक ही लंबाई है और s1 कोषगत s2 से छोटी है, तो।

मैं इसे हास्केल में कैसे कार्यान्वित करूं?

उत्तर

9

मैं था के साथ छड़ी का सुझाव: विश्वविद्यालय पिछले सप्ताह है, और हम इस सुंदर विकल्प Ord उदाहरण के साथ आया था निम्नलिखित की तरह कुछ का उपयोग करें:

smaller :: String -> String -> Bool 
smaller s1 s2 | len1 /= len2   = (len1 < len2) 
       | otherwise   = (s1 < s2) 
       where (len1, len2) = (length s1, length s2) 

यहाँ, एक नमूना रन है हग्स में:

 
Main> smaller "b" "aa" 
True 
Main> smaller "aa" "b" 
False 
Main> smaller "this" "that" 
False 
Main> smaller "that" "this" 
True 
+0

यह मेरे संस्करण की तुलना में स्पष्ट रूप से तेज़ है, क्योंकि यह केवल एक बार स्ट्रिंग की लंबाई की गणना करता है। यह इनपुट स्ट्रिंग्स पर प्रत्यक्ष पैटर्न मिलान करके शायद तेज़ी से भी बनाया जा सकता है, जिससे इस परिभाषा को विलय और 'लंबाई' फ़ंक्शन की परिभाषा मिलती है। –

+1

हास्केल सामान्यीकरण और अच्छी कोडिंग प्रथाओं के बारे में है, और इसकी एक बहुत अच्छी प्रकार (कक्षा) प्रणाली है। फ़ंक्शन को 'तुलना' के रूप में क्यों नहीं लिखें :: Ord a => [a] -> [a] -> ऑर्डरिंग 'या तो? –

+1

@ एलेक्सेंडर: यह निर्भर करता है कि ओपी क्या चाहता है।चूंकि ओपी ने काफी प्राथमिक प्रश्न पूछा है, शायद वह एक प्राथमिक उत्तर चाहता है? मुझे संदेह नहीं है कि हास्केल में ऐसे फ़ंक्शन को लिखने के लिए तेज़ और/या अधिक बेवकूफ तरीके हैं, लेकिन शायद ओपी सीखने में मदद करने के लिए चीजों को सरल रखना बेहतर है। –

5

इस प्रयास करें:

compare s1 s2 

(यह रिटर्न एलटी, EQ, या जी.टी.)।

+0

मुझे लगता है कि ओपी छोटे सामग्रियों को उनकी सामग्री के बावजूद लंबे तारों की तुलना में 'छोटा' होना चाहता है। "बी" "एए" जीटी की तुलना करें, लेकिन मुझे लगता है कि ओपी एक ऐसा कार्य चाहता है जो इस मामले में एलटी लौटाए। –

2

StringOrd का एक उदाहरण है और इसलिए आप स्ट्रिंग की तुलनात्मक रूप से तुलना करने के लिए उन सभी विधियों का उपयोग कर सकते हैं। जैसा कि एंड्रयू ने कहा, यह अनिवार्य रूप से compare है लेकिन तुलना ऑपरेटर, (<) दूसरों के बीच भी है।

smaller :: Ord a => a -> a -> Bool 
smaller a b = a < b 

यह सभी प्रकारOrd लागू करने के लिए काम करता है (और (<) के लिए वास्तव में सिर्फ एक कच्चे आवरण है), String भी शामिल है।

+0

मुझे लगता है कि ओपी छोटे सामग्रियों को उनकी सामग्री के बावजूद लंबे तारों की तुलना में 'छोटा' होना चाहता है। उदाहरण के लिए, छोटे "बी" "एए" को वापस लौटना चाहिए। (<) खाते में लंबाई नहीं लेता है इसलिए मुझे विश्वास नहीं है कि आपका उत्तर काफी है जो ओपी पूछ रहा है। –

2

सामान्य स्ट्रिंग की तुलना केवल लेक्सिकोोग्राफ़िकल ऑर्डरिंग पर काम करती है, स्ट्रिंग की लंबाई नहीं।

smaller :: String -> String -> Bool 
smaller s1 s2 | length s1 < length s2 = True 
       | length s1 > length s2 = False 
       | otherwise    = s1 < s2 

या थोड़ा अधिक सामान्य:

compareStrings :: String -> String -> Ordering 
compareStrings s1 s2 | length s1 < length s2 = LT 
        | length s1 > length s2 = GT 
        | otherwise    = compare s1 s2 

उदाहरण:

ghci> compare "ab" "z" 
LT 
ghci> compareStrings "ab" "z" 
GT 

तो तुम भी लंबाई के लिए जाँच करने के लिए अपने स्वयं के समारोह लिखने के लिए होगा

हम मोनोइड्स के साथ घूम रहे थे

instance Ord a => Ord [a] where 
    compare = comparing length 
       `mappend` comparing head `mappend` comparing tail 

लेकिन अगर आप काफी यह समझ में नहीं आता, मैं तुम्हें पहले परिभाषा ;-)

+2

लम्बाई की तुलना करने के कारण का एक हिस्सा उपयोगी है अन्य भाषाओं में स्ट्रिंग के स्ट्रिंग की कई कार्यान्वयन या स्ट्रिंग लम्बाई कैश करें। लाभ यह है कि अधिकांश स्ट्रिंग तुलना तब तारों की लंबाई के कार्य के रूप में समय ओ (1) लेती हैं। हास्केल में यह मामला नहीं है। मूल कार्यान्वयन के साथ सभी स्ट्रिंग तुलनाओं में तारों की लंबाई के कार्य के रूप में कम से कम ओ (मिनट (एम, एन)) समय लगेगा। – yfeldblum

+2

निश्चित रूप से, और यह भी सबसे तेज़ कार्यान्वयन संभव नहीं है। यह सिर्फ इतना है कि मैंने सोचा कि प्रश्नकर्ता ने तुलना के एक संस्करण के लिए कहा था जहां तारों को लेक्सिकोग्राफिकल क्रम से पहले लंबाई के लिए पहली बार चेक किया गया था। यह उपयोगी हो सकता है यदि आप तारों की एक सूची मुद्रित करना चाहते हैं और पहले छोटे तारों को मुद्रित करना पसंद करते हैं। –

+0

@ टॉम: मुझे यकीन नहीं है कि एस 2 एस 1 से अधिक लंबा होने पर आपका छोटा फ़ंक्शन सही तरीके से काम करता है। उदाहरण के लिए, छोटा "aa" "b" सत्य लौटाता है। ऐसा लगता है कि ओपी चाहता है कि समारोह इस मामले में झूठी वापसी करे। –

7

एक-पास समाधान:

lengthcompare :: Ord a => [a] -> [a] -> Ordering 
lengthcompare = lc EQ 
where 
    lc lx [] [] = lx 
    lc _ [] _ = LT 
    lc _ _ [] = GT 
    lc EQ (v:vs) (w:ws) = lc (compare v w) vs ws 
    lc lx (_:vs) (_:ws) = lc lx vs ws 

smaller :: Ord a => [a] -> [a] -> Bool 
smaller s1 s2 = lengthcompare s1 s2 == LT 
4

टॉम Lokhorst द्वारा mappend संस्करण का एक छोटा संस्करण से ऊपर:

import Data.Monoid (mappend) 
import Data.Ord (comparing) 

compareStrings :: String -> String -> Ordering 
compareStrings = comparing length `mappend` comparing id 

एक और तरीका है, tuples के आदेश का लाभ लेने:

import Data.Ord (comparing) 
import Control.Arrow ((&&&)) 

compareStrings :: String -> String -> Ordering 
compareStrings = comparing (length &&& id) 
+0

ओह ठीक है, मैं एक वैकल्पिक परिभाषा के बारे में सोच रहा था, लेकिन जब एक नया फ़ंक्शन परिभाषित करता है, तो आप स्पष्ट रूप से सूचियों पर मौजूदा ऑर्डरिंग का उपयोग कर सकते हैं। अच्छी परिभाषाएं! –

+0

इसके अलावा, मुझे वास्तव में तीर लाइब्रेरी सीखना शुरू करना होगा। मैं लगातार इन अच्छी सुरुचिपूर्ण परिभाषाओं के साथ आने वाले लोगों को देखता हूं, और यह केवल फ़ंक्शन इंस्टेंस का उपयोग कर रहा है ... –

+0

हां, ये अच्छे और छोटे हैं। आईडी की तुलना == तुलना करें, तो यहां एक और विकल्प है: लंबाई 'मैपेंड' तुलना की तुलना – Martijn

संबंधित मुद्दे

 संबंधित मुद्दे