2016-02-02 10 views
5

में अंतरिक्ष के साथ पायथन शब्दकोश प्रतिस्थापन मेरे पास एक स्ट्रिंग और एक शब्दकोश है, मुझे उस पाठ में dict कुंजी की हर घटना को प्रतिस्थापित करना होगा।कुंजी

text = 'I have a smartphone and a Smart TV' 
dict = { 
    'smartphone': 'toy', 
    'smart tv': 'junk' 
} 

कुंजी में कोई जगह नहीं है, तो मैं शब्द में पाठ तोड़ने के लिए और dict साथ एक के बाद एक की तुलना करेंगे। ऐसा लगता है कि ओ (एन) लिया गया। लेकिन अब कुंजी के अंदर जगह है इसलिए चीज अधिक समेकित है। कृपया मुझे ऐसा करने का अच्छा तरीका सुझाएं और कृपया ध्यान दें कि कुंजी टेक्स्ट के मामले से मेल नहीं खा सकती है।

अद्यतन

मैं इस समाधान के थिंक है लेकिन यह कुशल नहीं। हे (एम * n) या अधिक ...

for k,v in dict.iteritems(): 
    text = text.replace(k,v) #or regex... 

उत्तर

1

यदि टेक्स्ट में मुख्य शब्द एक-दूसरे के करीब नहीं है (कीवर्ड अन्य कीवर्ड) तो हम ऐसा कर सकते हैं। मेरे लिए हे (एन) ले लिया> "<

def dict_replace(dictionary, text, strip_chars=None, replace_func=None): 
    """ 
     Replace word or word phrase in text with keyword in dictionary. 

     Arguments: 
      dictionary: dict with key:value, key should be in lower case 
      text: string to replace 
      strip_chars: string contain character to be strip out of each word 
      replace_func: function if exist will transform final replacement. 
          Must have 2 params as key and value 

     Return: 
      string 

     Example: 
      my_dict = { 
       "hello": "hallo", 
       "hallo": "hello", # Only one pass, don't worry 
       "smart tv": "http://google.com?q=smart+tv" 
      } 
      dict_replace(my_dict, "hello google smart tv", 
         replace_func=lambda k,v: '[%s](%s)'%(k,v)) 
    """ 

    # First break word phrase in dictionary into single word 
    dictionary = dictionary.copy() 
    for key in dictionary.keys(): 
     if ' ' in key: 
      key_parts = key.split() 
      for part in key_parts: 
       # Mark single word with False 
       if part not in dictionary: 
        dictionary[part] = False 

    # Break text into words and compare one by one 
    result = [] 
    words = text.split() 
    words.append('') 
    last_match = ''  # Last keyword (lower) match 
    original = ''  # Last match in original 
    for word in words: 
     key_word = word.lower().strip(strip_chars) if \ 
        strip_chars is not None else word.lower() 
     if key_word in dictionary: 
      last_match = last_match + ' ' + key_word if \ 
         last_match != '' else key_word 
      original = original + ' ' + word if \ 
         original != '' else word 
     else: 
      if last_match != '': 
       # If match whole word 
       if last_match in dictionary and dictionary[last_match] != False: 
        if replace_func is not None: 
         result.append(replace_func(original, dictionary[last_match])) 
        else: 
         result.append(dictionary[last_match]) 
       else: 
        # Only match partial of keyword 
        match_parts = last_match.split(' ') 
        match_original = original.split(' ') 
        for i in xrange(0, len(match_parts)): 
         if match_parts[i] in dictionary and \ 
          dictionary[match_parts[i]] != False: 
          if replace_func is not None: 
           result.append(replace_func(match_original[i], dictionary[match_parts[i]])) 
          else: 
           result.append(dictionary[match_parts[i]]) 
      result.append(word) 
      last_match = '' 
      original = '' 

    return ' '.join(result) 
1

अपनी चाबी कोई रिक्त स्थान है, तो:

output = [dct[i] if i in dct else i for i in text.split()] 

' '.join(output) 

आप dict की डीसीटी बजाय का उपयोग करना चाहिए, तो यह समारोह में बनाया के साथ भिड़ना नहीं है dict()

यह डेटा फ़िल्टर करने के लिए dictionary comprehension, और ternary operator का उपयोग करता है।

अपनी चाबी रिक्त स्थान की क्या ज़रूरत है, तो आप सही हैं:

for k,v in dct.iteritems(): 
    string.replace('d', dct[d]) 

और हाँ, इस समय जटिलता मीटर * n हो जाएगा, जैसा कि आप डीसीटी में प्रत्येक कुंजी के लिए हर बार स्ट्रिंग के माध्यम से पुनरावृति करना है।

+0

कुंजी में स्पेस है, इसलिए आप –

+0

स्ट्रिंग प्रतिस्थापित नहीं कर सकते हैं, यदि स्ट्रिंग को इस my_dict = {"google": "याहू", "याहू": "google"} और टेक्स्ट "google yahoo से बड़ा है" –

0

सभी शब्दकोश कुंजी और इनपुट टेक्स्ट को कम मामले में छोड़ दें, इसलिए तुलना आसान है। अब ...

for entry in my_dict: 
    if entry in text: 
     # process the match 

यह मानता है कि शब्दकोश मैच को वारंट करने के लिए पर्याप्त छोटा है। यदि, इसके बजाय, शब्दकोश बड़ा है और पाठ छोटा है, तो आपको प्रत्येक शब्द, फिर प्रत्येक 2-शब्द वाक्यांश लेना होगा, और देखें कि वे शब्दकोश में हैं या नहीं।

क्या आप जाने के लिए पर्याप्त हैं?

+0

ताना में 3 शब्द, 4 शब्द हो सकते हैं ... कौन जानता है। और आपका एल्गोरिदम कुशल नहीं है। –

+0

मेरा मानना ​​है कि यह ** ओ (एन) ** शब्दों की बाध्य संख्या के लिए है। यदि यह केवल इनपुट लंबाई से ही सीमित है, तो यह ** ओ (एन^2) ** है - लेकिन इनपुट में वाक्यांशों को तोड़ने के लिए विराम चिह्न दिया गया है, ** एन ** भी सीमित है। क्या यह आपके आवेदन के लिए उपयुक्त है? – Prune

+0

यदि पाठ में प्रवेश की तुलना में ओ (एन) से अधिक लिया गया था और मेरे निर्देश में प्रवेश के लिए एक और ओ (एम) लिया गया तो ओ (एन * एम) –

0

आपको 1 (प्रत्येक व्यक्तिगत शब्द) से सभी पड़ोसी क्रमपरिवर्तनों को लेन (टेक्स्ट) (संपूर्ण स्ट्रिंग) तक परीक्षण करने की आवश्यकता है।

text = 'I have a smartphone and a Smart TV' 

array = text.lower().split() 

key_permutations = [" ".join(array[j:j + i]) for i in range(1, len(array) + 1) for j in range(0, len(array) - (i - 1))] 

>>> key_permutations 
['i', 'have', 'a', 'smartphone', 'and', 'a', 'smart', 'tv', 'i have', 'have a', 'a smartphone', 'smartphone and', 'and a', 'a smart', 'smart tv', 'i have a', 'have a smartphone', 'a smartphone and', 'smartphone and a', 'and a smart', 'a smart tv', 'i have a smartphone', 'have a smartphone and', 'a smartphone and a', 'smartphone and a smart', 'and a smart tv', 'i have a smartphone and', 'have a smartphone and a', 'a smartphone and a smart', 'smartphone and a smart tv', 'i have a smartphone and a', 'have a smartphone and a smart', 'a smartphone and a smart tv', 'i have a smartphone and a smart', 'have a smartphone and a smart tv', 'i have a smartphone and a smart tv'] 

अब हम शब्दकोश के माध्यम से स्थानापन्न:: आप पड़ोसी क्रमपरिवर्तन इस तरह से उत्पन्न कर सकते हैं

import re 

for permutation in key_permutations: 
    if permutation in dict: 
     text = re.sub(re.escape(permutation), dict[permutation], text, flags=re.IGNORECASE) 

>>> text 
'I have a toy and a junk' 

हालांकि इसके लिए आपको अधिक, सबसे लंबे समय तक पहले, तो उलटे क्रम में क्रमपरिवर्तन की कोशिश करना चाहता हूँ विशिष्ट वाक्यांशों के व्यक्तिगत शब्दों पर प्राथमिकता है।

+0

होगा: ओ क्या आप जटिलता को समझा सकते हैं? यह मेरे लिए बहुत कुछ दिखता है। ओ (एम^एन) हो सकता है @। @ –

0

आप रेगुलर एक्सप्रेशन के साथ बहुत आसानी से कर सकते हैं।

import re 

text = 'I have a smartphone and a Smart TV' 
dict = { 
    'smartphone': 'toy', 
    'smart tv': 'junk' 
} 

for k, v in dict.iteritems(): 
    regex = re.compile(re.escape(k), flags=re.I) 
    text = regex.sub(v, text) 

यह अभी भी dict कुंजी के प्रसंस्करण आदेश पर निर्भर करता है, अगर एक आइटम के लिए प्रतिस्थापन मूल्य खोज एक और आइटम के लिए शब्द का भाग होने की समस्या से ग्रस्त है।

+0

स्ट्रिंग प्रतिस्थापन विफल हो जाएगा यदि dict_ में कुछ myddict = {"google": "याहू", "याहू": "google"} और टेक्स्ट "google yahoo से बड़ा है" –

+1

जैसा कि मैंने जवाब में उल्लेख किया था –