class_docstr: KeywordProcessor
  
  Attributes:
      _keyword (str): Used as key to store keywords in trie dictionary.
          Defaults to '_keyword_'
      non_word_boundaries (set(str)): Characters that will determine if the word is continuing.
          Defaults to set([A-Za-z0-9_])
      keyword_trie_dict (dict): Trie dict built character by character, that is used for lookup
          Defaults to empty dictionary
      case_sensitive (boolean): if the search algorithm should be case sensitive or not.
          Defaults to False
  
  Examples:
      >>> # import module
      >>> from flashtext import KeywordProcessor
      >>> # Create an object of KeywordProcessor
      >>> keyword_processor = KeywordProcessor()
      >>> # add keywords
      >>> keyword_names = ['NY', 'new-york', 'SF']
      >>> clean_names = ['new york', 'new york', 'san francisco']
      >>> for keyword_name, clean_name in zip(keyword_names, clean_names):
      >>>     keyword_processor.add_keyword(keyword_name, clean_name)
      >>> keywords_found = keyword_processor.extract_keywords('I love SF and NY. new-york is the best.')
      >>> keywords_found
      >>> ['san francisco', 'new york', 'new york']
  
  Note:
      * loosely based on `Aho-Corasick algorithm <https://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_algorithm>`_.
      * Idea came from this `Stack Overflow Question <https://stackoverflow.com/questions/44178449/regex-replace-is-taking-time-for-millions-of-documents-how-to-make-it-faster>`_.
class_docstr_tok: ["KeywordProcessor","Attributes",":","_keyword","(","str",")",":","Used","as","key","to","store","keywords","in","trie","dictionary",".","Defaults","to","'_keyword_'","non_word_boundaries","(","set","(","str",")",")",":","Characters","that","will","determine","if","the","word","is","continuing",".","Defaults","to","set","(","[","A-Za-z0-9_","]",")","keyword_trie_dict","(","dict",")",":","Trie","dict","built","character","by","character",",","that","is","used","for","lookup","Defaults","to","empty","dictionary","case_sensitive","(","boolean",")",":","if","the","search","algorithm","should","be","case","sensitive","or","not",".","Defaults","to","False","Examples",":",">",">",">","#","import","module",">",">",">","from","flashtext","import","KeywordProcessor",">",">",">","#","Create","an","object","of","KeywordProcessor",">",">",">","keyword_processor","=","KeywordProcessor","(",")",">",">",">","#","add","keywords",">",">",">","keyword_names","=","[","'NY","'",",","'new-york","'",",","'SF","'","]",">",">",">","clean_names","=","[","'new","york","'",",","'new","york","'",",","'san","francisco","'","]",">",">",">","for","keyword_name",",","clean_name","in","zip","(","keyword_names",",","clean_names",")",":",">",">",">","keyword_processor.add_keyword","(","keyword_name",",","clean_name",")",">",">",">","keywords_found","=","keyword_processor.extract_keywords","(","'","I","love","SF","and","NY",".","new-york","is","the","best",".","'",")",">",">",">","keywords_found",">",">",">","[","'san","francisco","'",",","'new","york","'",",","'new","york","'","]","Note",":","*","loosely","based","on","`","Aho-Corasick","algorithm","<","https",":","\/\/en.wikipedia.org\/wiki\/Aho","%","E2","%","80","%","93Corasick_algorithm",">","`","_",".","*","Idea","came","from","this","`","Stack","Overflow","Question","<","https",":","\/\/stackoverflow.com\/questions\/44178449\/regex-replace-is-taking-time-for-millions-of-documents-how-to-make-it-faster",">","`","_","."]
docstr: Searches in the string for all keywords present in corpus.
  Keywords present are replaced by the clean name and a new string is returned.
  
  Args:
      sentence (str): Line of text where we will replace keywords
  
  Returns:
      new_sentence (str): Line of text with replaced keywords
  
  Examples:
      >>> from flashtext import KeywordProcessor
      >>> keyword_processor = KeywordProcessor()
      >>> keyword_processor.add_keyword('Big Apple', 'New York')
      >>> keyword_processor.add_keyword('Bay Area')
      >>> new_sentence = keyword_processor.replace_keywords('I love Big Apple and bay area.')
      >>> new_sentence
      >>> 'I love New York and Bay Area.'
docstr_tok: ["Searches","in","the","string","for","all","keywords","present","in","corpus",".","Keywords","present","are","replaced","by","the","clean","name","and","a","new","string","is","returned",".","Args",":","sentence","(","str",")",":","Line","of","text","where","we","will","replace","keywords","Returns",":","new_sentence","(","str",")",":","Line","of","text","with","replaced","keywords","Examples",":",">",">",">","from","flashtext","import","KeywordProcessor",">",">",">","keyword_processor","=","KeywordProcessor","(",")",">",">",">","keyword_processor.add_keyword","(","'Big","Apple","'",",","'New","York","'",")",">",">",">","keyword_processor.add_keyword","(","'Bay","Area","'",")",">",">",">","new_sentence","=","keyword_processor.replace_keywords","(","'","I","love","Big","Apple","and","bay","area",".","'",")",">",">",">","new_sentence",">",">",">","'","I","love","New","York","and","Bay","Area",".","'"]
code: def replace_keywords(self, sentence, max_cost=0):
      """Searches in the string for all keywords present in corpus.
      Keywords present are replaced by the clean name and a new string is returned.
  
      Args:
          sentence (str): Line of text where we will replace keywords
  
      Returns:
          new_sentence (str): Line of text with replaced keywords
  
      Examples:
          >>> from flashtext import KeywordProcessor
          >>> keyword_processor = KeywordProcessor()
          >>> keyword_processor.add_keyword('Big Apple', 'New York')
          >>> keyword_processor.add_keyword('Bay Area')
          >>> new_sentence = keyword_processor.replace_keywords('I love Big Apple and bay area.')
          >>> new_sentence
          >>> 'I love New York and Bay Area.'
  
      """
      if not sentence:
          # if sentence is empty or none just return the same.
          return sentence
      new_sentence = []
      orig_sentence = sentence
      if not self.case_sensitive:
          sentence = sentence.lower()
      current_word = ""
      current_dict = self.keyword_trie_dict
      current_white_space = ""
      sequence_end_pos = 0
      idx = 0
      sentence_len = len(sentence)
      curr_cost = max_cost
      while idx < sentence_len:
          char = sentence[idx]
          # when we reach whitespace
          if char not in self.non_word_boundaries:
              current_word += orig_sentence[idx]
              current_white_space = char
              # if end is present in current_dict
              if self._keyword in current_dict or char in current_dict:
                  # update longest sequence found
                  sequence_found = None
                  longest_sequence_found = None
                  is_longer_seq_found = False
                  if self._keyword in current_dict:
                      sequence_found = current_dict[self._keyword]
                      longest_sequence_found = current_dict[
                          self._keyword
                      ]
                      sequence_end_pos = idx
  
                  # re look for longest_sequence from this position
                  if char in current_dict:
                      current_dict_continued = current_dict[char]
                      current_word_continued = current_word
                      idy = idx + 1
                      while idy < sentence_len:
                          inner_char = sentence[idy]
                          if (
                              inner_char not in self.non_word_boundaries
                              and self._keyword
                              in current_dict_continued
                          ):
                              current_word_continued += orig_sentence[
                                  idy
                              ]
                              # update longest sequence found
                              current_white_space = inner_char
                              longest_sequence_found = (
                                  current_dict_continued[self._keyword]
                              )
                              sequence_end_pos = idy
                              is_longer_seq_found = True
                          if inner_char in current_dict_continued:
                              current_word_continued += orig_sentence[
                                  idy
                              ]
                              current_dict_continued = (
                                  current_dict_continued[inner_char]
                              )
                          elif curr_cost > 0:
                              next_word = self.get_next_word(
                                  sentence[idy:]
                              )
                              current_dict_continued, cost, _ = next(
                                  self.levensthein(
                                      next_word,
                                      max_cost=curr_cost,
                                      start_node=current_dict_continued,
                                  ),
                                  ({}, 0, 0),
                              )
                              idy += len(next_word) - 1
                              curr_cost -= cost
                              current_word_continued += next_word  # just in case of a no match at the end
                              if not current_dict_continued:
                                  break
                          else:
                              break
                          idy += 1
                      else:
                          # end of sentence reached.
                          if self._keyword in current_dict_continued:
                              # update longest sequence found
                              current_white_space = ""
                              longest_sequence_found = (
                                  current_dict_continued[self._keyword]
                              )
                              sequence_end_pos = idy
                              is_longer_seq_found = True
                      if is_longer_seq_found:
                          idx = sequence_end_pos
                          current_word = current_word_continued
                  current_dict = self.keyword_trie_dict
                  if longest_sequence_found:
                      curr_cost = max_cost
                      new_sentence.append(
                          longest_sequence_found + current_white_space
                      )
                      current_word = ""
                      current_white_space = ""
                  else:
                      new_sentence.append(current_word)
                      current_word = ""
                      current_white_space = ""
              else:
                  # we reset current_dict
                  current_dict = self.keyword_trie_dict
                  new_sentence.append(current_word)
                  current_word = ""
                  current_white_space = ""
          elif char in current_dict:
              # we can continue from this char
              current_word += orig_sentence[idx]
              current_dict = current_dict[char]
          elif curr_cost > 0:
              next_orig_word = self.get_next_word(orig_sentence[idx:])
              next_word = (
                  next_orig_word
                  if self.case_sensitive
                  else str.lower(next_orig_word)
              )
              current_dict, cost, _ = next(
                  self.levensthein(
                      next_word,
                      max_cost=curr_cost,
                      start_node=current_dict,
                  ),
                  (self.keyword_trie_dict, 0, 0),
              )
              idx += len(next_word) - 1
              curr_cost -= cost
              current_word += next_orig_word  # just in case of a no match at the end
          else:
              current_word += orig_sentence[idx]
              # we reset current_dict
              current_dict = self.keyword_trie_dict
              # skip to end of word
              idy = idx + 1
              while idy < sentence_len:
                  char = sentence[idy]
                  current_word += orig_sentence[idy]
                  if char not in self.non_word_boundaries:
                      break
                  idy += 1
              idx = idy
              new_sentence.append(current_word)
              current_word = ""
              current_white_space = ""
          # if we are end of sentence and have a sequence discovered
          if idx + 1 >= sentence_len:
              if self._keyword in current_dict:
                  sequence_found = current_dict[self._keyword]
                  new_sentence.append(sequence_found)
              else:
                  new_sentence.append(current_word)
          idx += 1
      return "".join(new_sentence)
  
imports: import os
  import string
  import io
label_desc: Use image node_id 20 for calling the KeywordProcessor obj's underlying member method code with example usage: obj.replace_keywords(sentence, max_cost) and returns: str, sentence