2011-08-18 5 views
17

मैं स्ट्रिंग में वर्णों की आवृत्ति को कैसे गिन सकता हूं और फिर उन्हें तालिका के प्रकार में आउटपुट कर सकता हूं?हास्केल में एक स्ट्रिंग में वर्णों की आवृत्ति को कैसे ढूंढें?

उदाहरण के लिए, मैं इनपुट अगर शब्द "खुश" परिणाम

h 1 
a 1 
p 2 
y 1 

होगा इस ASCII क्रम में आदेश दिया जा सकता है भी है कि प्रतिभाशाली होगा।

मुझे पता है कि मुझे गिनती फ़ंक्शन का उपयोग करने की आवश्यकता है, किसी अन्य संकेत की सराहना की जाएगी।

संपादित करें: सभी उत्तर शानदार हैं, केवल मैं हास्केल में ऐसे शुरुआती हूं कि मैं वास्तव में समझ नहीं पा रहा हूं कि वे क्या कर रहे हैं।

उत्तर

9

संभवतः कम कुछ है, लेकिन यह काम करता है:

Prelude> import Data.List 
Prelude Data.List> map (\x -> (head x, length x)) $ group $ sort "happy" 
[('h',1),('a',1),('p',2),('y',1)] 
+1

आप पहली बार इनपुट सॉर्ट करने के लिए की तरह '" अब्बा "' मामलों को कवर करना होगा जहां 'पी' की घटनाएं संगत नहीं हैं। – hammar

+0

धन्यवाद, तय। :-) –

+2

और ध्यान दें कि '(\ x -> (हेड एक्स, लम्बाई x)) == head &&& length', जहां' (&&&) '' Control.Arrow' से है। – Conal

39

सरल समाधान के चरित्र से आवृत्ति के लिए मध्यवर्ती मानचित्रण स्टोर करने के लिए एक Data.Map उपयोग करने के लिए है। फिर आप fromListWith का उपयोग करके आसानी से गणना कर सकते हैं। चूंकि Data.Map सॉर्ट किया गया है, इसलिए आप उन्हें ASCII ऑर्डर में मुफ्त में प्राप्त करते हैं।

λ> :m + Data.Map 
λ> let input = "happy" 
λ> toList $ fromListWith (+) [(c, 1) | c <- input] 
[('a',1),('h',1),('p',2),('y',1)] 

तो क्या यहाँ हो रहा है?

विचार Data.Map (एक वृक्ष नक्शा) बनाने के लिए अक्षरों और आवृत्तियों के रूप में अक्षरों के रूप में उपयोग करना है।

सबसे पहले, हम इनपुट स्ट्रिंग लेते हैं और एक घटना को इंगित करने के लिए 1 के साथ प्रत्येक वर्ण के tuples बनाते हैं।

λ> [(c, 1) | c <- input] 
[('h',1),('a',1),('p',1),('p',1),('y',1)] 

इसके बाद, हम fromListWith का उपयोग बार-बार किसी नक्शे में प्रत्येक कुंजी-मान पेयर डालकर इन कुंजी-मान जोड़ों से क्रमबद्ध नक्शा बनाने के लिए। हम इसे एक फ़ंक्शन भी देते हैं जिसका उपयोग तब किया जाएगा जब एक कुंजी पहले से ही मानचित्र में थी। हमारे मामले में, हम (+) का उपयोग करते हैं ताकि जब एक वर्ण कई बार देखा जाता है, तो हम मौजूदा योग में गिनती जोड़ते हैं।

अंत में हम नक्शा को toList का उपयोग करके कुंजी-मूल्य tuples की सूची में वापस ले जाते हैं।

+0

मुझे लगता है कि मैं बेवकूफ हूं, लेकिन क्या यह एक कार्यक्रम है? मैं इस तरह के एक नोब हैकेल में बहुत खेद है अगर यह एक बेवकूफ सवाल है। – Hagrid123

+0

@ हैग्रिड 123: उदाहरण एक जीएचसीआई (दुभाषिया) सत्र से लिया जाता है, जो आपको हास्केल स्रोत फ़ाइल में जो कुछ मिलेगा उससे थोड़ा अलग है। उदाहरण के लिए 'लेट' का उपयोग शीर्ष-स्तरीय बाइंडिंग के लिए किया जाता है और 'मॉड्यूल' को मॉड्यूल आयात करने के लिए उपयोग किया जा सकता है। – hammar

+2

रिकॉर्ड के लिए, एक जीएचसीआई प्रॉम्प्ट का हॉलमार्क '>' वर्ण है। जब आप पहली बार ghci लॉन्च करते हैं तो आपको शायद 'प्रीलूड>' दिखाई देगा; ध्यान दें कि दायरे में मॉड्यूल प्रॉम्प्ट में सूचीबद्ध हैं। हैमर का ghci प्रॉम्प्ट बाहर निकलता प्रतीत होता है। –

4

func xs = map (\a -> (head a, length a)) $ group $ sort xs

+0

'groupBy (\ x y -> x == y)' 'group' – newacct

+0

जैसा ही है, मुझे एहसास हुआ कि जिस क्षण मैंने इसे पोस्ट किया था। :) – Marii

0

मैं कदम से एक समाधान कदम scetch करेंगे। मानक कार्यों का उपयोग करके एक छोटा समाधान संभव है।

आप किसी क्रमित परिणाम चाहते हैं, इसलिए

result = sort cs 
    where 

सीएस tuples है, जिसकी पहली तत्व चरित्र और दूसरा तत्व है की एक सूची होगा बार ऐसा लगता है की संख्या है।

 cs = counts "happy" 
     counts [] = [] 
     counts (c:cs) = (c, length otherc + 1) : counts nonc where 
      (otherc, nonc) = partition (c==) cs 

यह सब कुछ है।

दिलचस्प बात यह है कि गणना == ऑपरेटर का समर्थन करने वाली वस्तुओं की किसी भी सूची पर काम करती है।

0
import Data.Array (Ix, accumArray, assocs) 

eltDist :: (Bounded a, Ix a, Eq b, Num b) => [a] -> [(a, b)] 
eltDist str = filter ((/=0) . snd) $ 
    assocs (accumArray (+) 0 (minBound, maxBound) [(i, 1) | i <- str]) 

"मिनीबाउंड" और "अधिकतमबाउंड" i के लिए अनुमानित प्रकार की सीमा पर निर्भर होने जा रहे हैं। के लिए चार यह 0 - 1,114,111 होगा, जो असाधारण है लेकिन असंभव नहीं है। यदि आप यूनिकोड वर्णों की गणना कर रहे थे तो यह विशेष रूप से सुविधाजनक होगा। यदि आप केवल ASCII तारों में रूचि रखते हैं, तो (0, 255) करेंगे। सरणी के बारे में एक अच्छी बात यह है कि उन्हें किसी भी प्रकार से अनुक्रमित किया जा सकता है जिसे पूर्णांक में मैप किया जा सकता है। Ix देखें।

assocs इंडेक्स खींचता है और सरणी से जोड़ों की सूची में जोड़ता है और अप्रयुक्त लोगों के फ़िल्टर डिस्पोजेक्ट करता है।

3

सूची समझ का उपयोग करें, किसी भी आयात या सॉर्टिंग की आवश्यकता नहीं है।

[ (x,c) | x<-['A'..'z'], let c = (length.filter (==x)) "happy", c>0 ] 

परिणाम:

[('a',1),('h',1),('p',2),('y',1)] 

ऊपर फ़िल्टर और पुनः लिखा जाता है (केवल के साथ चरित्र गिनती> 0) से:

[(x,(length.filter (==x)) "happy") | x<-['A'..'z']] 

स्पष्टीकरण:

  • एक सूची बनाएँ किसी भी वर्ण से मेल खाने वाले सभी पात्रों (ए..जेड) से मेल खाते हैं।
  • हर किरदार के लिए, इस सूची (== लंबाई) गिनती
  • चरित्र के साथ एक टपल में इस गणना रखो
+0

मुझे यह पसंद है! जब आप इनपुट स्ट्रिंग के सभी पात्रों की बजाय कुछ पात्रों के लिए आवृत्तियों में रुचि रखते हैं तो यह वास्तव में सहायक होता है। बहुत साफ़। –

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