parameters: (letter_case, reverse_letter_case=None)
return_statement: return ranges, range_lengths
docstring: Extract ranges from case mappings
      (the second param is optional, if it's not empty, a range will contains bidirectional conversions only).
  
      :param letter_id: An integer, representing the unicode code point of the character.
      :param letter_case: case mappings dictionary which contains the conversions.
      :param reverse_letter_case: Comparable case mapping table which contains the return direction of the conversion.
      :return: A table with the start points and their mapped value, and another table with the lengths of the ranges.
docstring_summary: Extract ranges from case mappings
      (the second param is optional, if it's not empty, a range will contains bidirectional conversions only).
docstring_tokens: Extract ranges from case mappings ( the second param is optional if it s not empty a range will contains bidirectional conversions only ) .
function: def extract_ranges(letter_case, reverse_letter_case=None):
      """
      Extract ranges from case mappings
      (the second param is optional, if it's not empty, a range will contains bidirectional conversions only).
  
      :param letter_id: An integer, representing the unicode code point of the character.
      :param letter_case: case mappings dictionary which contains the conversions.
      :param reverse_letter_case: Comparable case mapping table which contains the return direction of the conversion.
      :return: A table with the start points and their mapped value, and another table with the lengths of the ranges.
      """
  
      in_range = False
      range_position = -1
      ranges = []
      range_lengths = []
  
      for letter_id in sorted(letter_case.keys()):
          prev_letter_id = letter_id - 1
  
          # One-way conversions
          if reverse_letter_case is None:
              if len(letter_case[letter_id]) > 1:
                  in_range = False
                  continue
  
              if prev_letter_id not in letter_case or len(letter_case[prev_letter_id]) > 1:
                  in_range = False
                  continue
  
          # Two way conversions
          else:
              if not is_bidirectional_conversion(letter_id, letter_case, reverse_letter_case):
                  in_range = False
                  continue
  
              if not is_bidirectional_conversion(prev_letter_id, letter_case, reverse_letter_case):
                  in_range = False
                  continue
  
          conv_distance = calculate_conversion_distance(letter_case, letter_id)
          prev_conv_distance = calculate_conversion_distance(letter_case, prev_letter_id)
  
          if conv_distance != prev_conv_distance:
              in_range = False
              continue
  
          if in_range:
              range_lengths[range_position] += 1
          else:
              in_range = True
              range_position += 1
  
              # Add the start point of the range and its mapped value
              ranges.extend([prev_letter_id, ord(letter_case[prev_letter_id])])
              range_lengths.append(2)
  
      # Remove all ranges from the case mapping table.
      for idx in range(0, len(ranges), 2):
          range_length = range_lengths[idx // 2]
  
          for incr in range(range_length):
              del letter_case[ranges[idx] + incr]
              if reverse_letter_case is not None:
                  del reverse_letter_case[ranges[idx + 1] + incr]
  
      return ranges, range_lengths
function_tokens: def extract_ranges ( letter_case , reverse_letter_case = None ) : in_range = False range_position = - 1 ranges = [ ] range_lengths = [ ] for letter_id in sorted ( letter_case . keys ( ) ) : prev_letter_id = letter_id - 1 # One-way conversions if reverse_letter_case is None : if len ( letter_case [ letter_id ] ) > 1 : in_range = False continue if prev_letter_id not in letter_case or len ( letter_case [ prev_letter_id ] ) > 1 : in_range = False continue # Two way conversions else : if not is_bidirectional_conversion ( letter_id , letter_case , reverse_letter_case ) : in_range = False continue if not is_bidirectional_conversion ( prev_letter_id , letter_case , reverse_letter_case ) : in_range = False continue conv_distance = calculate_conversion_distance ( letter_case , letter_id ) prev_conv_distance = calculate_conversion_distance ( letter_case , prev_letter_id ) if conv_distance != prev_conv_distance : in_range = False continue if in_range : range_lengths [ range_position ] += 1 else : in_range = True range_position += 1 # Add the start point of the range and its mapped value ranges . extend ( [ prev_letter_id , ord ( letter_case [ prev_letter_id ] ) ] ) range_lengths . append ( 2 ) # Remove all ranges from the case mapping table. for idx in range ( 0 , len ( ranges ) , 2 ) : range_length = range_lengths [ idx // 2 ] for incr in range ( range_length ) : del letter_case [ ranges [ idx ] + incr ] if reverse_letter_case is not None : del reverse_letter_case [ ranges [ idx + 1 ] + incr ] return ranges , range_lengths