0
\$\begingroup\$

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]
\$\endgroup\$
7
  • 3
    \$\begingroup\$ Can you give an example of inputs and expected outputs? I find your question quite confusing \$\endgroup\$
    – Floris
    Commented May 10, 2014 at 19:11
  • \$\begingroup\$ @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. \$\endgroup\$ Commented May 10, 2014 at 19:55
  • 2
    \$\begingroup\$ "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". \$\endgroup\$
    – Floris
    Commented May 10, 2014 at 19:57
  • \$\begingroup\$ I have a problem that I solve with regex. Now I have two problems. blog.codinghorror.com/… \$\endgroup\$ Commented May 10, 2014 at 21:16
  • 2
    \$\begingroup\$ 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. \$\endgroup\$
    – LiavK
    Commented May 10, 2014 at 23:26

1 Answer 1

5
\$\begingroup\$

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)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.