2011-11-05 6 views
7

यह एक और सवाल में आया लेकिन मुझे लगा कि यह एक अलग सवाल के रूप में पूछना सर्वोत्तम है। वाक्यों की एक बड़ी सूची दें (100 हजार का आदेश):किसी दस्तावेज़ में शब्दों को अनुक्रमणित करने का सबसे प्रभावी तरीका?

[ 
"This is sentence 1 as an example", 
"This is sentence 1 as another example", 
"This is sentence 2", 
"This is sentence 3 as another example ", 
"This is sentence 4" 
] 

निम्न फ़ंक्शन को कोड करने का सबसे अच्छा तरीका क्या है?

def GetSentences(word1, word2, position): 
    return "" 

जहां दो शब्दों, word1, word2 और एक स्थिति position को देखते हुए समारोह सभी वाक्य है कि बाधा को संतुष्ट करने का सूची वापस आ जाएगी। उदाहरण के लिए:

GetSentences("sentence", "another", 3) 

वाक्य के सूचकांक के रूप में वाक्य 1 और 3 लौटना चाहिए। मेरे वर्तमान दृष्टिकोण इस तरह एक शब्दकोश उपयोग कर रहा था:

Index = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: []))) 

for sentenceIndex, sentence in enumerate(sentences): 
    words = sentence.split() 
    for index, word in enumerate(words): 
     for i, word2 in enumerate(words[index:): 
      Index[word][word2][i+1].append(sentenceIndex) 

लेकिन यह जल्दी से एक डाटासेट है कि आकार में लगभग 130 एमबी के रूप में मेरे 48GB रैम कम से कम 5 मिनट में समाप्त हो रहा है पर अनुपात से बाहर सब कुछ चल रही है। मुझे किसी भी तरह यह महसूस हो रहा है कि यह एक आम समस्या है लेकिन इसे कुशलतापूर्वक हल करने के तरीके पर कोई संदर्भ नहीं मिल रहा है। इस दृष्टिकोण के बारे में कोई सुझाव?

+0

बस स्पष्ट करने के लिए: वाक्य में दो शब्दों के बीच की दूरी 'स्थिति' है? – misha

+0

@ मिशा: हां। यह सही है। – Legend

+0

दो "वाक्य 1" होने के कारण भ्रमित है। क्या यह दूसरे "1" से मेल खाता था और पहले नहीं? – shookster

उत्तर

14

मूल्यों को संग्रहीत करने के लिए डेटाबेस का उपयोग करें।

  1. पहले एक तालिका (वे आईडी होना चाहिए) के लिए सभी वाक्य जोड़ें। आप इसे कह सकते हैं उदाहरण के लिए। sentences
  2. दूसरा, शब्दों सभी वाक्य (यह जैसे कहते हैं। words, प्रत्येक शब्द एक आईडी देना) के भीतर निहित के साथ तालिका बनाने के वाक्य 'तालिका रिकॉर्ड और शब्द' अलग तालिका के भीतर तालिका रिकॉर्ड के बीच संबंध की बचत (यह जैसे कहते हैं। sentences_words, इसमें दो कॉलम होना चाहिए, अधिमानतः word_id और sentence_id)।
  3. जब सभी का उल्लेख शब्दों से युक्त वाक्य के लिए खोज, अपने काम को सरल बनाया जाएगा:

    1. आप पहली बार words तालिका, जहां शब्द वास्तव में लोगों को आप के लिए खोज कर रहे हैं से रिकॉर्ड खोजना चाहिए। क्वेरी ऐसा दिखाई दे सकता:

      SELECT `id` FROM `words` WHERE `word` IN ('word1', 'word2', 'word3'); 
      
    2. दूसरे, आप तालिका sentences कि word_id मान आवश्यक है (words मेज से शब्द से सम्बंधित) से sentence_id मूल्यों को खोजने चाहिए। प्रारंभिक क्वेरी ऐसा दिखाई दे सकता:

      SELECT `sentence_id`, `word_id` FROM `sentences_words` 
      WHERE `word_id` IN ([here goes list of words' ids]); 
      

      जो इस को सरल किया जा सकता है:

      SELECT `sentence_id`, `word_id` FROM `sentences_words` 
      WHERE `word_id` IN (
          SELECT `id` FROM `words` WHERE `word` IN ('word1', 'word2', 'word3') 
      ); 
      
    3. फ़िल्टर अजगर भीतर परिणाम केवल sentence_id मूल्यों सभी आवश्यक word_id आप आईडी है कि वापस जाने के लिए जरुरत।

यह मूल रूप से एक समाधान फार्म का है कि सबसे अच्छा इस के लिए अनुकूल है में डेटा की बड़ी मात्रा में भंडारण के आधार पर है - डेटाबेस।

संपादित करें:

  1. आप केवल दो शब्द के लिए खोज करेंगे, तो आप और भी अधिक डीबीएमएस के पक्ष (लगभग सब कुछ) कर सकते हैं।
  2. ध्यान में रखते हुए आपको स्थिति अंतर भी चाहिए, आपको sentences_words तालिका के तीसरे कॉलम के भीतर शब्द की स्थिति को स्टोर करना चाहिए (इसे केवल position पर कॉल करें) और उचित शब्दों की खोज करते समय, आपको दोनों शब्दों से जुड़े इस मान के अंतर की गणना करनी चाहिए।
+2

+1 आपके समय के लिए बहुत बहुत धन्यवाद। मुझे लगता है कि मैं इसके साथ जाऊंगा। मैं इस पल के लिए स्क्लाइट का उपयोग करने के बारे में सोच रहा हूं लेकिन अगर यह शायद MySQL काम नहीं करता है। – Legend

+1

@Legend: धन्यवाद। मेरा मानना ​​है कि स्क्लाइट इसके लिए उपयुक्त है, अगर एक ही डेटाबेस में एक ही उपयोगकर्ता द्वारा एक डेटाबेस का उपयोग नहीं किया जाएगा। यदि केवल एक उपयोगकर्ता इसका उपयोग करेगा, तो मेरी राय में स्क्लाइट सबसे अच्छा है, इसलिए मैं आपकी पसंद से पूरी तरह से सहमत हूं। – Tadeck

+2

मैं एक बार फिर धन्यवाद करने के लिए वापस आया था। यह कहने में एक लंबा सफर तय करता है कि "सही नौकरी के लिए सही उपकरण का उपयोग करें" :) कोलेक्शन बनाने के लिए समय एक्स (एक्स> 12 से कम हो गया है और यह खत्म नहीं हुआ क्योंकि यह स्मृति समाप्त हो गया है!) घंटों से 1 घंटे अब उपयोग कर रहा है sqlite और यह भी भारी नहीं है! – Legend

2

यहां मैंने पाइथन में यह कैसे किया। हालांकि यह मानते हुए कि इसे एक से अधिक बार करने की आवश्यकता है, एक डीबीएमएस नौकरी के लिए सही उपकरण है। हालांकि यह मेरे लिए दस लाख पंक्तियों के साथ बहुत अच्छा काम करता प्रतीत होता है।

sentences = [ 
    "This is sentence 1 as an example", 
    "This is sentence 1 as another example", 
    "This is sentence 2", 
    "This is sentence 3 as another example ", 
    "This is sentence 4" 
    ] 

sentences = sentences * 200 * 1000 

sentencesProcessed = [] 

def preprocess(): 
    global sentences 
    global sentencesProcessed 
    # may want to do a regex split on whitespace 
    sentencesProcessed = [sentence.split(" ") for sentence in sentences] 

    # can deallocate sentences now 
    sentences = None 


def GetSentences(word1, word2, position): 
    results = [] 
    for sentenceIndex, sentence in enumerate(sentencesProcessed): 
     for wordIndex, word in enumerate(sentence[:-position]): 
      if word == word1 and sentence[wordIndex + position] == word2: 
       results.append(sentenceIndex) 
    return results 

def main(): 
    preprocess() 
    results = GetSentences("sentence", "another", 3) 
    print "Got", len(results), "results" 

if __name__ == "__main__": 
    main() 
+0

+1 इस दृष्टिकोण के लिए धन्यवाद। दरअसल, मैंने इसका परीक्षण किया और इसे एक बार के प्रश्नों के लिए सुपर फास्ट पाया। हालांकि, मैंने कई प्रश्न करने की कोशिश की लेकिन लुकअप का समय बहुत अधिक था जिसकी उम्मीद है क्योंकि कोई सूचकांक नहीं है। लेकिन निरर्थक, एक दिलचस्प दृष्टिकोण। धन्यवाद। – Legend

+0

@Legend: हाँ, यह हर बार जब आप पूछताछ करते हैं तो पूरे डेटासेट को देखता है। मैं बस इसे आजमा देना चाहता था :-) – shookster

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