Answer the question
In order to leave comments, you need to log in
How to implement an algorithm for constructing a string from a list of ordered integers?
I'm trying to write a function that takes an ordered list of integers, and should return a string in which if more than two numbers go in order, you need to replace it with an abbreviated notation. For example, if the input is a list of 1,2,3,5, the output should be 1-3.5. But if the input is 1,2,5, then it should remain 1,2,5.
Here is my function, but it only works correctly for a particular case (when there are more than 2 consecutive numbers). How to correct or it is possible to implement this algorithm differently?
def myfunc(intList,k):
if len(intList)==1:
return str(intList[0])
else:
if intList[1]-intList[0]==1:
if k==0:
k=+1
return str(intList[0])+'-'+str(myfunc(intList[1:],k))
if k==1:
return str(myfunc(intList[1:],k))
else:
k=0
return str(intList[0])+','+str(myfunc(intList[1:],k))
print(myfunc([1,2,3,4,7,9,11,13,14,15,16,17,19],0))
print(myfunc([5,6,15,16],0))
1-4,7,9,11,13-17,19
5-6,15-16
Answer the question
In order to leave comments, you need to log in
def fl(l):
if len(l) > 2:
return '%s-%s' % (l[0], l[-1])
elif len(l) == 2:
return '%s, %s' % (l[0], l[-1])
else:
return '%s' % l[0]
def cc(l):
r = []
b = []
for i in l:
if len(b) > 0:
if i - b[-1] == 1:
b.append(i)
else:
r.append(fl(b))
b = [i]
else:
b.append(i)
else:
r.append(fl(b))
return ', '.join(r)
If you want it easier, keep it. The logic is this: you need to insert the "-" symbol into the list where the difference between two adjacent numbers > 1. And then this list is converted to a string.
def getstr(l):
nl = [l[0],]
for i in range(1, len(l)):
if l[i] - nl[-1] > 1 and nl[-2] != '-':
nl.append('-')
nl.append(l[i])
return nl
l = [1,2,3,4,7,9,11,13,14,15,16,17,19]
nl = getstr(l)
print(','.join(nl).replace(',-,', '-'))
It seems to me that Andrey has a great code, but here's another option. Similar to yours, but without the recursion.
You just need to keep both the beginning and the end of the range. Well, with the last element, a slightly special task - almost the same as simply closing the range, but with a slight correction. Otherwise, it is either duplicated or not added at all.
def closeInt(rS, rE):
if rE - rS == 1:
return ", " + str(rE)
if rE - rS > 1:
return "-" + str(rE)
return ""
def shortify(intlist):
result = str(intlist[0])
rangeStart = intlist[0]
rangeEnd = intlist[0]
for i in range(1, len(intlist)):
if intlist[i] == intlist[i-1] + 1:
rangeEnd += 1
else:
result += closeInt(rangeStart, rangeEnd)
result += ", " + str(intlist[i])
rangeStart = intlist[i]
rangeEnd = intlist[i]
result += closeInt(rangeStart, intlist[-1])
return result
print(shortify([1]))
print(shortify([2,3]))
print(shortify([2,4]))
print(shortify([4,5,6]))
print(shortify([1,2,3,4,7,9,11,13,14,15,16,17,19]))
print(shortify([1,2,4,7,8,11,12,13,14,15,16,18,19]))
print(shortify([1,2,3,4,7,9,11,13,14,15,17,18,19]))
Here is the working code. The whole simple essence of the method is to replace with 0 all numbers that have left-right neighbors -1 and + 1, respectively, then run through the obtained values, replacing all consecutive 0s with '-'. Glue the result through ',', and finally replace ',-,' with '-'
from itertools import groupby
def drop_inner(nums):
for a, b, c in zip([0, 0] + nums, [0] + nums + [0], nums + [0, 0]):
if b:
yield 0 if a and c and (a + 1 == b == c - 1) else b
def shorten(nums):
return ','.join(
str(x) if x else '-' for x, _ in groupby(drop_inner(nums))
).replace(',-,', '-')
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question