nodes: 0, module; 1, function_definition; 2, function_name:items_sharing_ngrams; 3, parameters; 4, block; 5, identifier:self; 6, identifier:query; 7, expression_statement; 8, comment:# From matched string to number of N-grams shared with query string; 9, expression_statement; 10, comment:# Dictionary mapping n-gram to string to number of occurrences of that; 11, comment:# ngram in the string that remain to be matched.; 12, expression_statement; 13, for_statement; 14, return_statement; 15, comment:"""Retrieve the subset of items that share n-grams the query string.
  
          :param query: look up items that share N-grams with this string.
          :return: mapping from matched string to the number of shared N-grams.
  
          >>> from ngram import NGram
          >>> n = NGram(["ham","spam","eggs"])
          >>> sorted(n.items_sharing_ngrams("mam").items())
          [('ham', 2), ('spam', 2)]
          """; 16, assignment; 17, assignment; 18, identifier:ngram; 19, call; 20, block; 21, identifier:shared; 22, identifier:shared; 23, dictionary; 24, identifier:remaining; 25, dictionary; 26, attribute; 27, argument_list; 28, try_statement; 29, identifier:self; 30, identifier:split; 31, identifier:query; 32, block; 33, except_clause; 34, for_statement; 35, identifier:KeyError; 36, block; 37, pattern_list; 38, call; 39, block; 40, pass_statement; 41, identifier:match; 42, identifier:count; 43, attribute; 44, argument_list; 45, expression_statement; 46, comment:# match as many occurrences as exist in matched string; 47, if_statement; 48, subscript; 49, identifier:items; 50, call; 51, comparison_operator:remaining[ngram][match] > 0; 52, block; 53, attribute; 54, identifier:ngram; 55, attribute; 56, argument_list; 57, subscript; 58, integer:0; 59, expression_statement; 60, expression_statement; 61, expression_statement; 62, identifier:self; 63, identifier:_grams; 64, call; 65, identifier:setdefault; 66, identifier:match; 67, identifier:count; 68, subscript; 69, identifier:match; 70, augmented_assignment; 71, call; 72, augmented_assignment; 73, attribute; 74, argument_list; 75, identifier:remaining; 76, identifier:ngram; 77, subscript; 78, integer:1; 79, attribute; 80, argument_list; 81, subscript; 82, integer:1; 83, identifier:remaining; 84, identifier:setdefault; 85, identifier:ngram; 86, dictionary; 87, subscript; 88, identifier:match; 89, identifier:shared; 90, identifier:setdefault; 91, identifier:match; 92, integer:0; 93, identifier:shared; 94, identifier:match; 95, identifier:remaining; 96, identifier:ngram
code: def items_sharing_ngrams(self, query):
          """Retrieve the subset of items that share n-grams the query string.
  
          :param query: look up items that share N-grams with this string.
          :return: mapping from matched string to the number of shared N-grams.
  
          >>> from ngram import NGram
          >>> n = NGram(["ham","spam","eggs"])
          >>> sorted(n.items_sharing_ngrams("mam").items())
          [('ham', 2), ('spam', 2)]
          """
          # From matched string to number of N-grams shared with query string
          shared = {}
          # Dictionary mapping n-gram to string to number of occurrences of that
          # ngram in the string that remain to be matched.
          remaining = {}
          for ngram in self.split(query):
              try:
                  for match, count in self._grams[ngram].items():
                      remaining.setdefault(ngram, {}).setdefault(match, count)
                      # match as many occurrences as exist in matched string
                      if remaining[ngram][match] > 0:
                          remaining[ngram][match] -= 1
                          shared.setdefault(match, 0)
                          shared[match] += 1
              except KeyError:
                  pass
          return shared