2

The purpose of the below code is to return minimum pipe slopes for inputted diameters. The code returns an error if the DIA input (in meters) is not within the key values.

D_MINSLOPE = {100:60, 150:100, 225:300, 300:400, 375:550, 450:700, 525:750, 600:900, 675:1050, 750:1200, 825:1380, 900:1600, 1050:2000, 1200:2400, 1350:2800, 1500:3250, 1650:3700, 1800:4200}

def minslope(DIA):
    DIA_mm = round(DIA * 1000)
    Slope = 1/D_MINSLOPE[DIA_mm]
    return Slope

I am currently going to resolve the issue with 'try/except' 'if/elif' to round up through the different bases (50, 75, 150) as per this answered question.

Is there a more pythonic way to round to the key values?

I note the question is similar to the linked which is in regards to arrays.

2 Answers2

3

IIUC, Following example from related question, you can search for closest key in the dictionary. For e.g. if you want to search for 500:

min(D_MINSLOPE, key=lambda x:abs(x-500))

will return 525 which is the closest value in the keys of dictionary.

So, you can try changing function as:

def minslope(DIA):
    # convert Diameter (m) to Diameter (mm)
    DIA_mm = DIA * 1000        
    # get closest value
    DIA_cv = min(D_MINSLOPE, key=lambda x:abs(x-DIA_mm))   
    Slope = 1/D_MINSLOPE[DIA_cv]
    return Slope
niraj
  • 17,498
  • 4
  • 33
  • 48
0

Not quite the same approach as above, but this was my take on the question. I recreated the dictionary of keys as intervals, and if DIA falls in that interval it would return that value, rather than the use of the closest.

Also you might want to change 1 to 1.0, to make sure that your value returns a floating number instead of an integer. (I'm assuming that is what you are after).

D_MINSLOPE = {100:60, 150:100, 225:300, 300:400, 375:550, 450:700, 525:750,
              600:900, 675:1050, 750:1200, 825:1380, 900:1600, 1050:2000,
              1200:2400, 1350:2800, 1500:3250, 1650:3700, 1800:4200}


def change_dict(dictionary):
    """
    Changes the dictionary to contain intervals as keys

    Returns:
        {(1651, 1800): 4200, (301, 375): 550,
         (1201, 1350): 2800, (451, 525): 750,
         (751, 825): 1380, (526, 600): 900,
         (1, 100): 60, (676, 750): 1200,
         (1051, 1200): 2400, (1351, 1500): 3250,
         (826, 900): 1600, (901, 1050): 2000,
         (376, 450): 700, (151, 225): 300,
         (101, 150): 100, (1501, 1650): 3700,
         (601, 675): 1050, (226, 300): 400}
    """
    new_dict = {}
    temp = [0] + sorted(D_MINSLOPE.keys())
    i = 0
    while i < len(D_MINSLOPE.keys()):
        key = temp[i+1]; value = D_MINSLOPE[key]
        new_key = (temp[i] + 1, temp[i+1])
        new_dict[new_key] = value
        i += 1
    return new_dict


def minslope(DIA):
    DIA_mm = round(DIA * 1000)
    D_MINSLOPE_2 = change_dict(D_MINSLOPE)    # Change dictionary keys

    # Find the key in which DIA_mm falls under
    key = None
    for i in D_MINSLOPE_2:
        if (i[0] <= DIA) and (i[1] >= DIA):
            key = i
            break

    # Change 1 to 1.0, as it needs to be a float number to output decimals
    # otherwise it would probably output 0 as an integer.
    return 1.0/D_MINSLOPE_2[key]    
kkcheng
  • 402
  • 4
  • 8