colarat
colarat

Reputation: 33

List comprehension if/else and for iteration order

I have a CSV file that contains book chapters either as single chapters or chapter ranges delimited by commas, e.g. 1,2,4-6,12.

Given this input '1,2,4-6,12', I want a list ['1','2','4','5','6','12'] as output

Something along the lines of:

chps=[str(x) for x in chp_range(entry)) if '-' in entry else entry  for entry in chapters.split(',') ]

which doesn't work.

Function chp_range('4-6') returns a range(4,6) object.

I've tried a lot of variations, but still haven't been able to get the order of conditionals and iteration right. How can I get this code to work?

Upvotes: 0

Views: 106

Answers (6)

Sffffff
Sffffff

Reputation: 659

Not a one-liner but if you are interested in a recursive solution. Please check it up.

a = '1,2,4-6,12'
inp = [num  if '-' not in num else [str(i) for i in range(int(num[0]),int(num[-1])+1)] for num in a.split(',') ]
ans = []

def flatten(inp,ans):

  while inp:
    tmp = inp.pop()

    if type(tmp) == str:
      ans.append(tmp)
    else:
      flatten(tmp,ans)

  return 

flatten(inp,ans)

ans[::-1]

Upvotes: 0

Kelly Bundy
Kelly Bundy

Reputation: 27588

What you were trying to do:

chps = [str(x)
        for entry in chapters.split(',')
        for x in (chp_range(entry) if '-' in entry else [entry])]

Try it online!

Upvotes: 2

Mazhar
Mazhar

Reputation: 1064

from itertools import chain


def chp_range(entry):
    x, y = map(int, entry.split('-'))
    return map(str, range(x, y+1))


chps = [
    chp_range(entry) if '-' in entry else entry for entry in chapters.split(',')]
list(chain(*chps))

Upvotes: 1

Kedar U Shet
Kedar U Shet

Reputation: 583

YOu can use extend for range as follows:

string = '1,2,4-6,12'
string = string.split(',')
chapters = [] 
for i in string:
    if '-' in i:
        a,b = i.split('-')
        chapters.extend(range(int(a),int(b)+1))
    else:
        chapters.append(int(i))
print(chapters)

Upvotes: 0

Selcuk
Selcuk

Reputation: 59184

If it has to be a one-liner, this should work:

>>> [str(x) for c in chapters.split(",") for x in range(int(c.split("-")[0]), int(c.split("-")[-1])+1)]
['1', '2', '4', '5', '6', '12']

You can't conditionally nest your comprehensions, so your chp_range function is of little value when used in a comprehension.

Upvotes: 4

Julien
Julien

Reputation: 15071

Don't try to use list comprehension for the sake of, only if it's actually easier / more readable:

lst = []
for x in s.split(','): 
    if '-' in x:
        start, end = x.split('-')
        lst.extend([str(i) for i in range(int(start), int(end)+1)])
    else:
        lst.append(x)

Upvotes: 3

Related Questions