5
\$\begingroup\$

Kata: https://www.codewars.com/kata/range-extraction/python

A format for expressing an ordered list of integers is to use a comma separated list of either

  • individual integers
  • or a range of integers denoted by the starting integer separated from the end integer in the range by a dash, '-'. The range includes all integers in the interval including both endpoints. It is not considered a range unless it spans at least 3 numbers. For example ("12, 13, 15-17")

Complete the solution so that it takes a list of integers in increasing order and returns a correctly formatted string in the range format.

Example:

solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20])
 # returns "-6,-3-1,3-5,7-11,14,15,17-20"

Courtesy of rosettacode.org

My Code

def solution(lst):
 res = []
 if lst:
 tmp, i, ln = lst[0], 0, len(lst)
 while i < ln:
 tmp, j = lst[i], i
 while j < ln - 1 and lst[j+1] == lst[j]+1:
 j += 1
 if j - i > 1:
 tmp = str(lst[i]) + "-" + str(lst[j])
 i = j+1
 else:
 i = (j if j > i else i+1)
 res.append(tmp)
 return ",".join(str(x) for x in res)
asked Mar 6, 2019 at 8:10
\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

Grouping

If you need to group anything using; groupby is probably the easiest way

Here we can use a itertools.groupby recipe to group the consecutive ranges:

>>> for _, g in groupby(enumerate(lst), lambda i_x : i_x[0] - i_x[1]):
... print([x for _, x in g])
[-6]
[-3, -2, -1, 0, 1]
[3, 4, 5]
[7, 8, 9, 10, 11]
[14, 15]
[17, 18, 19, 20]

Yielding the correct representation

Now all is left is to check whether there are more then 2 items in the range, and return the range. Else return all the numbers in the range normally

We can make this a generator, which yields either the range or a number, and afterwards join them together.

Full Code

def group_consecutives(lst):
 for _, g in groupby(enumerate(lst), lambda i_x : i_x[0] - i_x[1]):
 r = [x for _, x in g]
 if len(r) > 2:
 yield f"{r[0]}-{r[-1]}"
 else:
 yield from map(str, r)
def range_extraction(lst):
 return ','.join(group_consecutives(lst))
answered Mar 6, 2019 at 9:17
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.