Search code examples
pythonmath

Dynamically calculating ranges in Python


I have a series of files that are named "x.tif" where "x" is an integer I have a need to sort these files into folders for each number range.

The top level of folders should be in the millions, for example, 0-999999, 1000000-1999999 The next level of folders should be in thousands, for example, 0-999, 1000-1999

Its not so much the Python that's tripping me up, but the actual maths to calculate the ranges

The end result should look something like this Desired result example

Of course I could do this with hardcoded ranges, but I'd rather avoid typing out a huge elif statement for each thousand within each million.

I've been trying to use divmod() which works as expected for numbers below one thousand, but I can't work out what I need to do to make this dynamic so it could conceivably work out the ranges for any number fed into it.

def get_number_range(file_to_move): 

    file_number = file_to_move
    try:
        mod_calc_thou = divmod(int(file_number), 1000)
    except ValueError:
        self.mission_failed(file_to_move, reason="Not a number")
        return False, False
    try: 
        mod_calc_mil = divmod(int(file_number), 1000000)
    except ValueError:
        return False, False
    thousands_range = mod_calc_thou[0] + 999
    millions_range = mod_calc_mil[0] + 9999999
    thousands_range_folder = f"{str(mod_calc_thou[0])}-{thousands_range}"
    millionsths_range_folder = f"{str(mod_calc_mil[0])}-{millions_range}"
    print(thousands_range_folder)
    print(millionsths_range_folder)

print("First")
get_number_range("530")
#Should output 0-999 and 0-999999
print("Second")
get_number_range("1842888")
#Should output, 1842000-1842999, 1000000-1999999
print("Third")
get_number_range("19874")
#Should output 19000-19999, 0-999999

Solution

  • You can use the modulo % operation to compute the reminder of your file number, and subtract that reminder to get the base number fi of the ranges. The top number of the ranges is then, fi + Li - 1.

    n = 19874
    
    L1 = 1000000  # Top-level
    L2 = 1000  # Next-level
    
    # Compute the base of the ranges
    f1 = n - (n % L1)
    f2 = n - (n % L2)
    
    # Compute the whole range
    r1 = f1, f1 + L1 - 1
    r2 = f2, f2 + L2 - 1
    
    print(r2, r1)
    

    This could easily be adapted to more than two levels.

    n = 1842888
    
    # The levels in increasing order
    levels = [1000, 1000000]
    
    # Compute the base of the ranges
    f = [n - (n % l) for l in levels]
    # Compute the whole range
    r = [(f, f + l - 1) for (f, l) in zip(f, levels)]
    
    print(r)