nodes: 0, module; 1, function_definition; 2, function_name:reduceByKeyLocally; 3, parameters; 4, block; 5, identifier:self; 6, identifier:func; 7, expression_statement; 8, expression_statement; 9, function_definition; 10, function_definition; 11, return_statement; 12, comment:"""
          Merge the values for each key using an associative and commutative reduce function, but
          return the results immediately to the master as a dictionary.
  
          This will also perform the merging locally on each mapper before
          sending results to a reducer, similarly to a "combiner" in MapReduce.
  
          >>> from operator import add
          >>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
          >>> sorted(rdd.reduceByKeyLocally(add).items())
          [('a', 2), ('b', 1)]
          """; 13, assignment; 14, function_name:reducePartition; 15, parameters; 16, block; 17, function_name:mergeMaps; 18, parameters; 19, block; 20, call; 21, identifier:func; 22, call; 23, identifier:iterator; 24, expression_statement; 25, for_statement; 26, expression_statement; 27, identifier:m1; 28, identifier:m2; 29, for_statement; 30, return_statement; 31, attribute; 32, argument_list; 33, identifier:fail_on_stopiteration; 34, argument_list; 35, assignment; 36, pattern_list; 37, identifier:iterator; 38, block; 39, yield; 40, pattern_list; 41, call; 42, block; 43, identifier:m1; 44, call; 45, identifier:reduce; 46, identifier:mergeMaps; 47, identifier:func; 48, identifier:m; 49, dictionary; 50, identifier:k; 51, identifier:v; 52, expression_statement; 53, identifier:m; 54, identifier:k; 55, identifier:v; 56, attribute; 57, argument_list; 58, expression_statement; 59, attribute; 60, argument_list; 61, assignment; 62, identifier:m2; 63, identifier:items; 64, assignment; 65, identifier:self; 66, identifier:mapPartitions; 67, identifier:reducePartition; 68, subscript; 69, conditional_expression:func(m[k], v) if k in m else v; 70, subscript; 71, conditional_expression:func(m1[k], v) if k in m1 else v; 72, identifier:m; 73, identifier:k; 74, call; 75, comparison_operator:k in m; 76, identifier:v; 77, identifier:m1; 78, identifier:k; 79, call; 80, comparison_operator:k in m1; 81, identifier:v; 82, identifier:func; 83, argument_list; 84, identifier:k; 85, identifier:m; 86, identifier:func; 87, argument_list; 88, identifier:k; 89, identifier:m1; 90, subscript; 91, identifier:v; 92, subscript; 93, identifier:v; 94, identifier:m; 95, identifier:k; 96, identifier:m1; 97, identifier:k
code: def reduceByKeyLocally(self, func):
          """
          Merge the values for each key using an associative and commutative reduce function, but
          return the results immediately to the master as a dictionary.
  
          This will also perform the merging locally on each mapper before
          sending results to a reducer, similarly to a "combiner" in MapReduce.
  
          >>> from operator import add
          >>> rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
          >>> sorted(rdd.reduceByKeyLocally(add).items())
          [('a', 2), ('b', 1)]
          """
          func = fail_on_stopiteration(func)
  
          def reducePartition(iterator):
              m = {}
              for k, v in iterator:
                  m[k] = func(m[k], v) if k in m else v
              yield m
  
          def mergeMaps(m1, m2):
              for k, v in m2.items():
                  m1[k] = func(m1[k], v) if k in m1 else v
              return m1
          return self.mapPartitions(reducePartition).reduce(mergeMaps)