संक्षेप में
ऐसा लगता है कि आपकी समस्या का तेज़ समाधान एक REGEX, या एक FSA (परिमित राज्य ऑटोमेटन) को परिभाषित करना है, जो दस्तावेजों की सभी संभावित शुरुआत को पहचानता है (झूठी सकारात्मकता की अनुमति है, जो वास्तव में दस्तावेज़ के अनुरूप नहीं होगा)। फिर आप अपने इनपुट पर इसे बहुत तेज़ी से चला सकते हैं ताकि अगली जगह की पहचान हो सके जहाँ कुछ त्रुटियों के साथ एक दस्तावेज़ शुरू हो सके। यह एक दस्तावेज़ शुरू करने के लिए कुछ गलत स्थिति पैदा कर सकता है, लेकिन उन्हें पार्सर द्वारा मान्यता दी जाएगी और छोड़ दिया जाएगा।
तो Finite State Automaton वह पार्सर नाम हो सकता है जिसे आप खोज रहे थे। :)
समस्या
व्यावहारिक समस्या को समझना हमेशा कठिन होता है, खासकर जब शब्दावली की कई व्याख्या हो सकती है। पार्स वन शब्द को कॉन्टेक्स्ट-फ्री (CF) अस्पष्ट शब्दों के लिए गढ़ा गया (afaik), जिसमें कई पार्स-ट्री हैं। यह कुछ हद तक वाक्यों के एक जाली या अन्य प्रकार के व्याकरण के लिए सामान्यीकृत किया जा सकता है। इसलिए अर्ली, जीएलआर, मारपा और व्युत्पन्न पार्सर (कई अन्य हैं) के बारे में सभी जवाब जो इस मामले में प्रासंगिक नहीं थे।
लेकिन यह स्पष्ट रूप से नहीं है कि आपके मन में क्या है। आप एक अद्वितीय स्ट्रिंग को पार्स करना चाहते हैं जो कि अस्पष्ट दस्तावेजों का एक क्रम है, और प्रत्येक के लिए एक पार्स-ट्री या किसी प्रकार का संरचित प्रतिनिधित्व प्राप्त करें, क्योंकि आप वास्तव में यह नहीं कहते हैं कि आपके दस्तावेजों का वाक्यविन्यास कैसे परिभाषित किया जाता है, यह कहां से आता है देखने का एक औपचारिक भाषा बिंदु। आपके पास एक एल्गोरिथ्म और टेबल है जो किसी दस्तावेज़ की शुरुआत में पार्सिंग का काम करेगा। ऐसा ही होगा।
वास्तविक समस्या यह है कि आपके दस्तावेज़ की धारा में काफी कचरा है जो दस्तावेजों को अलग करता है। और ऐसा लगता है कि आपकी कठिनाई इस कचरे को जल्दी से स्कैन करने के लिए है। आपकी वर्तमान तकनीक शुरुआत में शुरू करने की है, और पहले चरित्र से स्कैन करने की कोशिश करें, और जब तक कि यह विफल न हो जाए, तब तक अगले वर्ण पर पुनरारंभ करें, जब तक कि आप एक संपूर्ण दस्तावेज़ स्कैन नहीं कर लेते। फिर आप दस्तावेज़ को स्कैन करने के बाद पहले चरित्र से बताते हुए दोहराते हैं।
वह भी अपने उत्तर के दूसरे भाग में @amon द्वारा सुझाया गया समाधान है ।
यह बहुत तेज़ समाधान नहीं हो सकता है (मेरे पास परीक्षण करने का कोई तरीका नहीं है), क्योंकि यह संभावना नहीं है कि दस्तावेज़ की शुरुआत में पार्सर के कोड को बहुत कुशलता से अनुकूलित किया जाए। सामान्य उपयोग में यह केवल एक बार ऐसा करता है, ताकि यह अनुकूलन के दृष्टिकोण से एक गर्म स्थान न हो। इसलिए, इस समाधान के साथ आपकी मध्यम खुशी बहुत आश्चर्य की बात नहीं है।
तो आपको वास्तव में क्या चाहिए एक एल्गोरिथ्म जो जल्दी से एक दस्तावेज़ की शुरुआत पा सकता है जो कचरे के बड़े पैमाने पर शुरू होता है। और आप भाग्यशाली हैं: इस तरह के एल्गोरिदम मौजूद हैं। और मुझे यकीन है कि आप इसे जानते हैं: इसे REGEX की खोज कहा जाता है।
सरल उपाय
आपको यह करने के लिए अपने दस्तावेज़ों के विनिर्देश का विश्लेषण करना है कि ये दस्तावेज़ कैसे शुरू होते हैं। मैं आपको बिल्कुल नहीं बता सकता कि कैसे, क्योंकि मुझे यकीन नहीं है कि उनके सिंटैक्स विनिर्देश को औपचारिक रूप से कैसे व्यवस्थित किया जाता है। संभवतः वे सभी एक परिमित सूची के कुछ शब्द से शुरू करते हैं, संभवतः कुछ विराम चिह्न या संख्याओं के साथ मिश्रित होते हैं। कि आप की जाँच करने के लिए है।
आपको जो करना है वह एक परिमित राज्य ऑटोमेटोन (FSA) को परिभाषित करना है, या अधिकांश प्रोग्रामर के लिए एक नियमित अभिव्यक्ति (REGEX) के समकक्ष है जो किसी दस्तावेज़ के पहले कुछ वर्णों को पहचान सकता है: अधिक, बेहतर, लेकिन इसकी बहुत आवश्यकता नहीं है बड़ा (जैसा कि समय और स्थान ले सकता है)। यह आपके दस्तावेज़ों के विनिर्देश से करना अपेक्षाकृत आसान होना चाहिए, और संभवतः एक प्रोग्राम के साथ स्वचालित रूप से किया जा सकता है जो आपके दस्तावेज़ों के विनिर्देश को पढ़ता है।
एक बार जब आप अपने regexp का उत्पादन कर लेते हैं, तो आप अपने इनपुट स्ट्रीम पर इसे अपने पहले (या अगले) दस्तावेज़ की शुरुआत में बहुत जल्दी प्राप्त करने के लिए चला सकते हैं:
मैं मानता हूं:
- docstart
एक regex है जो सभी दस्तावेजों की शुरुआत से मेल खाता है
- search(regex, stream)
एक ऐसा फ़ंक्शन है जो stream
एक विकल्प के लिए खोज करता है जो मेल खाता है regex
। जब यह वापस लौटता है, तो स्ट्रीम को इसके मिलान प्रत्यय से घटाकर पहले मिलान के विकल्प से शुरू किया जाता है, या खाली स्ट्रीम से कोई मेल नहीं मिलता है।
- parse(stream)
धारा की शुरुआत से एक दस्तावेज़ को पार्स करने का प्रयास करता है (इसके बारे में क्या बचा है), और जो कुछ भी प्रारूप में पार्स ट्री को वापस करता है, या विफल रहता है। जब वह वापस लौटता है, तो धारा के दस्तावेज़ के अंत के तुरंत बाद स्थिति में शुरू होने वाले इसके प्रत्यय घटाव तक धारा कम हो जाती है। यदि पार्स विफल हो जाता है तो यह अपवाद कहता है।
forest = empty_forest
search(docstart, stream)
while stream is not empty:
try:
forest = forest + parse(stream)
except
remove first character from stream
search(docstart, stream)
ध्यान दें कि पहले चरित्र को हटाना आवश्यक है ताकि अगली खोज फिर से उसी मैच को न मिले।
बेशक, धारा को छोटा करना एक छवि है। यह सिर्फ स्ट्रीम पर इंडेक्स हो सकता है।
एक अंतिम नोट यह है कि आपके रेगेक्स को बहुत सटीक होने की आवश्यकता नहीं है, जब तक कि यह सभी शुरुआत को पहचानता है। यदि यह कभी-कभी एक स्ट्रिंग को पहचानता है जो एक दस्तावेज़ की शुरुआत (झूठी सकारात्मक) नहीं हो सकती है, तो एकमात्र जुर्माना पार्सर के लिए एक बेकार कॉल की लागत है।
ताकि संभवतः उपयोगी होने पर रेगेक्स को सरल बनाने में मदद मिल सके।
तेजी से समाधान की संभावना के बारे में
उपरोक्त समाधान ज्यादातर मामलों में बहुत अच्छी तरह से काम करना चाहिए। हालाँकि, यदि आपके पास वास्तव में बहुत अधिक कचरा और फ़ाइल को संसाधित करने के लिए टेराबाइट्स हैं, तो अन्य एल्गोरिदम हो सकते हैं जो तेजी से चलते हैं।
यह विचार बॉयर-मूर स्ट्रिंग सर्च एल्गोरिदम से लिया गया है । यह एल्गोरिथ्म बहुत तेजी से एकल स्ट्रिंग के लिए एक धारा खोज सकता है क्योंकि यह स्ट्रिंग के एक संरचनात्मक विश्लेषण का उपयोग करता है, जिससे अधिकांश स्ट्रीम को पढ़ना छोड़ दिया जाता है, उन्हें देखने के बिना भी टुकड़ों पर कूद जाता है। यह एक स्ट्रिंग के लिए सबसे तेज़ खोज एल्गोरिथ्म है।
थ्रश कठिनाई यह है कि एकल स्ट्रिंग के बजाय, रेगेक्स को खोजने के लिए इसका अनुकूलन बहुत ही नाजुक लगता है और आप जिस विचार पर विचार कर रहे हैं, उसके आधार पर यह काम भी नहीं कर सकता है। बदले में आप उन दस्तावेजों के वाक्यविन्यास पर निर्भर हो सकते हैं जिन्हें आप पार्स कर रहे हैं। लेकिन मुझे इस पर बहुत अधिक भरोसा मत करो क्योंकि मेरे पास मेरे द्वारा पाए गए दस्तावेजों को सावधानीपूर्वक पढ़ने का समय नहीं था।
मैं आपको वेब पर मिले एक या दो बिंदुओं के साथ छोड़ रहा हूं, जिनमें से एक जाहिरा तौर पर एक रेफरीड शोध पत्र है , लेकिन आपको इसे अधिक सट्टा, संभवतः शोधपूर्ण माना जाना चाहिए, केवल तभी विचार किया जाना चाहिए जब आपके पास मजबूत प्रदर्शन समस्याएं थीं। और शायद शेल्फ प्रोग्राम में से कोई भी नहीं है जो इसे करेगा।