# Finding the lowest decimal number for a given integer

Some telephone operators have submitted their price lists including price per minute for different phone number prefixes.

Some test data, 2 price lists, look like this:

Operator A:
1  0.9
268    5.1
46     0.17
4620   0.0
468    0.15
4631   0.15
4673   0.9
46732  1.1
Operator B:
1  0.92
44     0.5
46     0.2
467    1.0
48     1.2


I want to find the lowest decimal number (the decimal number is a price per minute tax) for a given integer (where the integer is a telephone number or a prefix) in multiple data structures that I represented as Python tuples e.g. o1={1:0.1,2:0.21} and then a list of those [o1,o2].

I found that this batch processing looking code seem to respond the expected result, but could it be done with a regex or more efficient, more readable, or other design improvement?

opa = {1:0.9, 268:5.1, 46:0.17, 4620:0.0, 468:0.15, 4631:0.15, 4673:0.9, 46732:1.1}
opb = {1:0.92, 44:0.5, 46:0.2, 467:1.0, 48:1.2}
oplist=[opa,opb]

def get(self):
n = int(self.request.get('n', '46'))

#for all ops
matchlist = []
matched_ops = []
matched_n=[0]
cheapest_index={}
cheapest_ops={}
index=0
while(n>0):
index=0
for operator in oplist:
try:
var = operator[n]
if not operator in matched_ops and n>=max(matched_n) :
matchlist.append(var)
matched_ops.append(operator)
cheapest_ops[var]=operator
cheapest_index[var]=index
matched_n.append(n)
except KeyError:
pass
index=index+1
n=int(n/10)

#find cheapest
pricematch = min(matchlist)
operator = cheapest_ops[pricematch]
result_op=cheapest_index[pricematch]

• Can you give an example of inputs and expected outputs? I find your question quite confusing – Floris May 10 '14 at 19:11
• @Floris I added my usage of python's builtin {} and [] with test data that are supposed to match the price listing for telephone number routing given a prefix, so 1 might not be routable while 17 could be and such conditions that would make me think that a regex could be used. Now I appear to get the match I want so the code I posted might be done with a regex more efficiently. But I'm not sure that a regex is preferable. The example input telphone number should be e.g. 46705551234 and then return the lowest decimal match for the opa, opb... in the example data set just added. – Niklas R. May 10 '14 at 19:55
• "match the price listing for telephone number routing". I'm sorry, still lacking context. You are giving inputs. What are the expected outputs. "return the lowest decimal match" still doesn't mean anything to me - what do you consider a "decimal match". – Floris May 10 '14 at 19:57
• I have a problem that I solve with regex. Now I have two problems. blog.codinghorror.com/… – Martin York May 10 '14 at 21:16
• Agreed, this is still confusing. Please describe the problem you are trying to solve, and give us a complete example. Also, {1: 0.1, 2: 0.21} is not a tuple, it's a dictionary. – LiavK May 10 '14 at 23:26

If I understand what you're looking for correctly, it's the cheapest rate for a particular phone number.

If you already have the rates of each operator as a dictionary of key/value pairs, then you don't need a regex at all. The following code finds the cheapest rate in a set of dictionaries:

opa = {1:0.9, 268:5.1, 46:0.17, 4620:0.0, 468:0.15, 4631:0.15, 4673:0.9, 46732:1.1}
opb = {1:0.92, 44:0.5, 46:0.2, 467:1.0, 48:1.2}
phone_number_prefixes = []
prefix_sets = [opa, opb]

for prefix_set in prefix_sets:
phone_number_prefixes.extend([prefix for prefix in prefix_set.keys()])

phone_number_prefixes = list(set(phone_number_prefixes))  # get rid of duplicates.

cheapest_rates = {}
for prefix in phone_number_prefixes:
rate = float('inf')  # everything is less than infinity! ;)
for prefix_set in prefix_sets:
if prefix not in prefix_set:
continue
if prefix_set[prefix] < rate:
rate = prefix_set[prefix]
cheapest_rates.update({prefix: rate})


This gives:

{1: 0.9, 44: 0.5, 46: 0.17, 48: 1.2, 268: 5.1, 467: 1.0, 468: 0.15, 4620: 0.0, 4631: 0.15, 4673: 0.9, 46732: 1.1}


If you actually need to parse strings such as '46732 1.1' into dictionary key/value pairs, a regex would be a good fit for solving that problem. A little quick fiddling suggests that something like (\d+)\s*(\d+\.?\d*) would capture what you're looking for. This RE matches: (\d+) one or more digits, \s* zero or more whitespaces and (\d+\.?\d*) one or more digits followed by zero or one decimal points followed by zero or more digits. You can use this pattern by compiling it, folloed by python's re.split(string) method.

pattern = re.compile('(\d+)\s+(\d+\.?\d*)')
numbers = pattern.match('46732    1.1')
key, value = numbers.groups()
key = int(key)
value = float(value)