2010-09-14 24 views
12

क्या सूची में अद्वितीय तत्वों की गणना करने के लिए मानक उच्च-आदेश फ़ंक्शंस का सीधा-आगे संयोजन है?सूची में अद्वितीय तत्वों की गणना

हैं क्रम महत्वपूर्ण नहीं है उदाहरण के लिए के लिए

[1, 1, 4, 0, 4, 4] 

परिणाम

[(1,2), (4,3), (0,1)] 
+2

क्रम महत्वपूर्ण है? यदि ऐसा है तो आदेश क्या है? पहली घटना का आदेश? – sepp2k

उत्तर

10

कुछ होगा यह काम करता है:

map (\[email protected](x:_) -> (x, length xs)) . group . sort 

group . sort आप सूचियों की एक सूची दे देंगे जहां एक दूसरे के बराबर सभी तत्व एक ही उपन्यास में समूहित होते हैं (बिना सोर के टी, केवल लगातार बराबर तत्वों को एक साथ समूहीकृत किया जाएगा)। map फिर प्रत्येक sublist को (element, lengthOfSublist) -tuple में बदल देता है।

यदि आप पहली घटना के परिणाम को ऑर्डर करना चाहते हैं, तो आप प्रत्येक तत्व में इंडेक्स जोड़ने के लिए zip का उपयोग कर सकते हैं, फिर समूहिंग के बाद, उस इंडेक्स द्वारा फिर से सॉर्ट करें और फिर इंडेक्स को हटा दें।

+0

इस तरह की सूची बड़ी सूचियों पर बहुत महंगा हो सकती है। तेजी से प्रदर्शन के लिए केनीटीएम या एसडीसीडब्ल्यूसी के समाधानों का उपयोग करना बेहतर हो सकता है। – GeneralBecos

+0

@GeneralBecos नक्शा बनाने से सॉर्टिंग धीमा क्यों होगा? दोनों 'ओ (एन लॉग एन) 'हैं। – sepp2k

+0

मानते हुए कि आप एक आवृत्ति वितरण कर रहे हैं, केवल सबसे खराब मामले में तत्वों की संख्या सूची में तत्वों की संख्या के समान होगी। अधिक सामान्य परिदृश्य में, वितरण में तत्वों की संख्या बहुत छोटी होगी। औसतन, नक्शा इस तरह से बेहतर प्रदर्शन करेगा। – GeneralBecos

6

आइटमों को व्यवस्थित करने के लिए सबसे आसान बात यह होगी कि "समूह" का उपयोग उन्हें समान तत्वों की उप-सूचियों में रखने के लिए करें, और फिर प्रत्येक उप-सूची में आइटमों को गिनें।

map (\xs -> (head xs, length xs)) . group . sort 
+4

जिस तरह से आप '\ xs -> (head xs, length xs) '' head &&& लंबाई ', Control.Arrow मॉड्यूल का उपयोग कर – sdcvvc

6

सूची केवल पूर्णांकों है, तो आप भी इस्तेमाल कर सकते हैं

import qualified Data.IntMap as I 

countElems1 :: [Int] -> [(Int, Int)] 
countElems1 = I.toList . foldr (\k -> I.insertWith (+) k 1) I.empty 

(हालांकि अनुकूलन के साथ संकलित करने के लिए याद रखें, अन्यथा इस 2x group . sort विधि की तुलना में धीमी हो जाएगा। -O2 के साथ यह थोड़ा तेज है 14% तक।)

तुम भी multisetpackages जो

के रूप में सरल समारोह में आता है में से एक इस्तेमाल कर सकते हैं
import qualified Math.Combinatorics.Multiset as S 
countElems4 = S.toCounts . S.fromList 

लेकिन कम कुशल होने के नाते।

उपरोक्त सभी समाधान मूल आदेश को अनदेखा करते हैं।

+0

और यह कंटेनर लाइब्रेरी में हालिया गति सुधार के बिना है, मैं शर्त लगाऊंगा। –

1

सॉर्ट किए गए डेटा पर केवल run length encoding के बारे में आपकी बात क्या है: मुफ्त ऑनलाइन पुस्तक रियल वर्ल्ड हास्केल में great example of this है। आप इसे runLengthEncoder के माध्यम से रखने से पहले सूची को सॉर्ट करना चाहेंगे।

+0

यह * नहीं * आरएलई है। आरएलई '[(1,2), (4,1), (0,1), (4,2)] ' – kennytm

+0

@ केनीटीएम कृपया ध्यान दें कि मैंने 'क्रमबद्ध डेटा पर' कहा था। इसलिए काफी आरएलई नहीं है लेकिन लगभग क्रमबद्ध इनपुट के साथ मुझे लगता है कि यह है, है ना? –

13

का उपयोग Data.Map और टपल वर्गों:

count = Map.fromListWith (+) . map (, 1) 

(Map.toList जोड़े यदि आप एक सूची की जरूरत है।)

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