我有一个电话号码范围,例如:
3331234-3332345
我需要编写一个将其转换为前缀列表的函数:
3331234
...
3331239
333124
...
333129
33313
...
33319
33320
...
33322
333231
333232
333233
3332341
...
3332345
问题没那么容易。我不需要获取范围开始和结束之间的数字列表。
我有一个电话号码范围,例如:
3331234-3332345
我需要编写一个将其转换为前缀列表的函数:
3331234
...
3331239
333124
...
333129
33313
...
33319
33320
...
33322
333231
333232
333233
3332341
...
3332345
问题没那么容易。我不需要获取范围开始和结束之间的数字列表。
My working code. It not very quick, too. Optimizations welcome.
def diap_to_prefix(a, b):
lst = ['%0*d'%(max(len(str(a)), len(str(b))), x) for x in range(int(a), int(b)+1)]
new_lst = []
while len(lst) != len(new_lst):
lst = new_lst or lst
new_lst = []
c = lst[0]
tmp_lst = [c]
for i in lst[1:]:
if c[:-1] == i[:-1]:
c = i
tmp_lst.append(c)
else:
if len(tmp_lst) == 10:
new_lst.append(c[:-1])
else:
new_lst.extend(tmp_lst)
c = i
tmp_lst = [c]
if len(tmp_lst) == 10:
new_lst.append(c[:-1])
else:
new_lst.extend(tmp_lst)
return lst
My new more optimal solution (py3.4)
def diap_to_prefix(a, b):
def inner(aa, bb, p):
if p == 1:
if a <= aa <= b:
yield aa
return
for d in range(aa, bb + 1, p):
if a <= d and d + p - 1 <= b:
yield d // p
elif not (bb < a or aa > b):
for i in range(10):
yield from inner(d + i * p // 10, d + (i + 1) * p // 10 - 1, p // 10)
a, b = int(a), int(b)
p = 10**(max(len(str(x)) for x in (a, b)) - 1)
yield from inner(a // p * p, b // p * p + p - 1, p)
您需要获取以“-”分隔的值的公共前缀,因此:
.split
获取这些并遍历它们,直到找到不同之处phone_len
数字并为最大值(用九)做同样的事情这里是:
phone_len = 7
R = "33312345-3332345".split("-")
prefix = ""
for i in range(len(R[0])):
if R[0][i] == R[1][i]:
prefix += R[0][i]
else:
break
m = int(R[0]+"0"*(phone_len-len(R[0])))
M = int(R[1]+"9"*(phone_len-len(R[0])))
phones = [str(n) for n in range(m, M+1)]
Here's a sketch of one way to handle this problem. I've used ellipses to mark the spots where you'll need to fill in the details explained in the comments. I'd write a function to derive the initial value of 'maxpower', everything else is simple enough to be written inline.
firstnumber = 3331234
lastnumber = 3332345
current = firstnumber
while current <= lastnumber:
# Find the largest power of 10 that exactly divides 'current'.
# Call this value 'maxpower'. 'maxpower' is a candidate for the
# size of the block of numbers that will be represented by the
# next output value.
maxpower = ... # 1, 10, 100, 1000, 10000, and so on
# If a block of size 'maxpower' would take us past the
# 'lastnumber', we can't use that block size. We must try a
# smaller block. Divide 'maxpower' by 10 until the block size
# becomes acceptable.
while (current + maxpower) > ... :
maxpower /= 10
# Now 'maxpower' is the largest acceptable size for the next
# block, so the desired prefix is 'current' divided by 'maxpower'.
# Emit that value, then add 'maxpower' to 'current' to get the new
# 'current' value for the next iteration.
print ...
current += maxpower
My working code. It not very quick, but working. Optimizations welcome.
def fill(root, prefix, value, parent, pkey):
if len(prefix) > 1:
if prefix[0] in root:
fill(root[prefix[0]], prefix[1:], value, root, prefix[0])
if pkey:
if len(parent[pkey]) == 10:
parent[pkey] = value
elif type(root) == type({}):
root[prefix[0]] = {}
fill(root[prefix[0]], prefix[1:], value, root, prefix[0])
if pkey:
if len(parent[pkey]) == 10:
parent[pkey] = value
elif type(root) == type({}):
root[prefix[0]] = value
if pkey:
if len(parent[pkey]) == 10:
parent[pkey] = value
return root
def compact(prefixes, current):
if not type(prefixes) == type({}):
return [current]
else:
rlist = []
for k, v in prefixes.iteritems():
rlist.extend(compact(v, current + k))
continue
return rlist
if __name__ == '__main__':
plist = {}
for x in range(4440000, 4490000):
fill(plist, str(x), 'value', plist, None)
#print plist
print compact(plist, '')