2010-05-24 19 views
8

से अधिक से अधिक संख्या की एक श्रृंखला से मेल खाते हैं मैं इस तरह कुछ डेटा है कहते हैं:regex संख्यात्मक डेटा प्रसंस्करण: एक्स

number_stream = [0,0,0,7,8,0,0,2,5,6,10,11,10,13,5,0,1,0,...] 

मैं इसे संसाधित करने के लिए "बम्प्स" कि एक निश्चित पैटर्न को पूरा की तलाश करना चाहते हैं।

कल्पना कीजिए संख्या पर काम कर रहा है, जहां [[> = 5]] का प्रतिनिधित्व करता है के लिए मैं अपने खुद के अनुकूलित regex भाषा है किसी भी संख्या> = 5. मैं इस मामले पर कब्जा करना चाहते हैं:

([[ >=5 ]]{3,})[[ <3 ]]{2,} 

दूसरे शब्दों में, मैं किसी भी समय मैं आगे देखने के लिए और एक पंक्ति में 3 या उससे अधिक मूल्यों> = 5 देखें कब्जा शुरू होते हैं और किसी भी समय मैं आगे देख कर आपको 2 + महत्व देता है पर कब्जा बंद करना चाहते हैं < 3. तो मेरी उत्पादन किया जाना चाहिए:

>>> stream_processor.process(number_stream) 
[[5,6,10,11,10,13,5],...] 

ध्यान दें कि पहले 7,8,... को अनदेखा किया गया है क्योंकि यह एल नहीं है पर्याप्त मात्रा में, और कैप्चर 0,1,0... से पहले समाप्त होता है।

मुझे stream_processor ऑब्जेक्ट भी पसंद है, मैं बाद में process कॉल में अधिक डेटा पास कर सकता हूं, और पूरा होने के बाद कैप्चर किए गए हिस्सों को वापस कर सकता हूं।

मैंने इसे करने के लिए कुछ कोड लिखा है, लेकिन यह घृणित और राज्य-मशीनी था, और मुझे ऐसा महसूस करने में मदद नहीं मिल रही है कि मुझे कुछ स्पष्ट याद आ रही है। यह साफ करने के लिए कोई विचार?

+0

मैं विशेष रूप से एक और घोषणात्मक, पठनीय वर्णन से नट-किरकिरा तर्क को अलग करने का एक तरीका ढूंढ रहा हूं। मैं या तो एक और प्राकृतिक भाषा (जैसे प्रोलॉग या एफ #) का उपयोग कर झुका रहा था, या एक अच्छी तरह से परीक्षण मॉड्यूल में हार्ड-टू-रीड कोड को encapsulating। फिर भी, मैं उम्मीद कर रहा था कि मुझे अतिरिक्त कोड का एक गुच्छा लिखना पड़ेगा ... –

उत्तर

3

राज्य मशीनें (कुछ अतिरिक्त एक्स्ट्रा के साथ समृद्ध, चूंकि रेगेक्स एफएसएम की तुलना में भाषाओं की एक विस्तृत श्रृंखला से मेल खा सकता है) नियमित अभिव्यक्ति इंजनों को लागू करने के लिए एक सामान्य दृष्टिकोण है, तो अच्छे कार्यान्वयन की तलाश में समान दृष्टिकोण क्यों नहीं दिखना चाहिए आपकी वांछित "रेगेक्स जैसी" संरचनाओं का?

दरअसल, मैं एक वास्तविक आरई इंजन के लिए कोड से शुरू करने पर विचार करता हूं (पीपीपी स्रोतों में एक पायथन-कोडित एक है, जिसके लिए मेरकोरियल पेड़ here है), केवल "प्राइमेटिव्स" को बदलना (आप नहीं करते हैं उदाहरण की आवश्यकता है \w या \s, लेकिन आपको <5, >3, आदि की आवश्यकता है) और *, +, और इसी तरह के लिए अधिकांश वाक्यविन्यास और कार्यान्वयन को रखने की आवश्यकता है। इस तरह की एक परियोजना, रास्ते से खुले सोर्सिंग के लायक होगा।

1

एक राज्य मशीन यहां उचित समाधान है।

  • परस्पर पुनरावर्ती कार्यों का एक सेट जहां समारोह चल रहा है वर्तमान स्थिति का प्रतिनिधित्व करता है के रूप में Hardwired: वहाँ एक को लागू करने के दो सामान्य तरीके हैं। यह बहुत ही कुशल हो सकता है लेकिन पूंछ कॉल उन्मूलन, trampolines या goto की आवश्यकता है।

  • वर्तमान स्थिति का प्रतिनिधित्व करने वाली डेटा संरचना के रूप में नकली और उस राज्य के एक समारोह और राज्य को अपडेट करने वाला एक नया इनपुट डेटाम।

यह सामान कार्यात्मक प्रोग्रामिंग की रोटी और मक्खन है।यहां है ही समाधान उत्तरार्द्ध शैली में लिखा

> let rec skip = function 
    | _, yss, [] -> yss 
    | [_; _; _] as ys, yss, xs -> record ([], ys, yss, xs) 
    | ys, yss, x::xs when x >= 5 -> skip (x::ys, yss, xs) 
    | ys, yss, x::xs -> skip ([], yss, xs) 
    and record = function 
    | ys', ys, yss, [] -> (ys' @ ys) :: yss 
    | [_; _], ys, yss, xs -> skip ([], ys :: yss, xs) 
    | ys', ys, yss, x::xs when x < 3 -> record (x::ys', ys, yss, xs) 
    | ys', ys, yss, x::xs -> record ([], x::ys' @ ys, yss, xs);; 
val skip : int list * int list list * int list -> int list list 
val record : int list * int list * int list list * int list -> int list list 

> let run xs = skip([], [], xs) |> List.map List.rev |> List.rev;; 
val run : int list -> int list list 

> run [0;0;0;7;8;0;0;2;5;6;10;11;10;13;5;0;1;0];; 
val it : int list list = [[5; 6; 10; 11; 10; 13; 5]] 

और:

> type 'a state = 
    | Skip of 'a list 
    | Record of 'a list * 'a list;; 
type 'a state = 
    | Skip of 'a list 
    | Record of 'a list * 'a list 

> let rec apply (state, yss) x = 
    match state, yss with 
    | Skip([_; _; _] as ys), yss -> apply (Record([], ys), yss) x 
    | Skip ys, yss when x >= 5 -> Skip(x::ys), yss 
    | Skip ys, yss -> Skip[], yss 
    | Record([_; _], ys), yss -> apply (Skip[], ys :: yss) x 
    | Record(ys', ys), yss when x < 3 -> Record (x::ys', ys), yss 
    | Record(ys', ys), yss -> Record ([], x::ys' @ ys), yss;; 
val apply : int state * int list list -> int -> int state * int list list 

> let run xs = 
    match List.fold apply (Skip [], []) xs with 
    | Skip _, yss -> yss 
    | Record(ys', ys), yss -> (ys' @ ys) :: yss 
    |> List.map List.rev |> List.rev;; 
val run : int list -> int list list 

> run [0;0;0;7;8;0;0;2;5;6;10;11;10;13;5;0;1;0];; 
val it : int list list = [[5; 6; 10; 11; 10; 13; 5]] 

नोट यहां आपकी समस्या को एफ # में पूर्व शैली में लिखा करने के लिए एक सुरुचिपूर्ण समाधान है और अपने खुद के डेटा सेट पर चलने पहला समाधान एक बार में पूरे इनपुट को कैसे खाता है जबकि बाद में एक समय में एक ही डाटाम काटता है और एक और राज्य को एक और डेटम खाने के लिए तैयार करता है। नतीजतन, बाद में fold का उपयोग करके प्रत्येक डेटाम पर लागू किया जाता है और अंतिम आधा खाने वाला राज्य लौटने से पहले उचित रूप से उपभोग किया जाना चाहिए।

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