0

Aim

I would like to generate a sequence as list in python, such as:

['s1a', 's1b', 's2a', 's2b', ..., 's10a', 's10b']

Properties:

  • items contain a single prefix
  • numbers are sorted numerical
  • suffix is alternating per number

Approach

To get this, I applied the following code, using an xrange and comprehensive list approach:

# prefix
p = 's'
# suffix
s = ['a', 'b']
# numbers
n = [ i + 1 for i in list(xrange(10))]
# result
[ p + str(i) + j for i, j in zip(sorted(n * len(s)), s * len(n)) ]

Question

Is there a more simple syntax to obtain the results, e.g. using itertools? Similar to this question?

1
  • FWIW, sorted(n * len(s)) is an inefficient way to create that list, it would be better to do the replication inside the list comprehension that creates n. Also, list(xrange(...)) is an anti-pattern: if you want an actual list, just use range. (Of course, in Python 3, range returns a range object, not a list, so you do have to wrap it in a list call when you want an actual list). Commented Feb 3, 2017 at 12:12

5 Answers 5

5

A doubled-for list comprehension can accomplish this:

['s'+str(x)+y for x in range(1,11) for y in 'ab']
Sign up to request clarification or add additional context in comments.

2 Comments

I count the usage of doubled list comprehension, as well as range instead xrange as improvement. Will accept answer in case no better solutions are found. Thanks.
@setempler: using range also makes it compatible with Python 3. :)
3

itertools.product might be your friend:

all_combos = ["".join(map(str, x)) for x in itertools.product(p, n, s)]

returns:

['s1a', 's1b', 's2a', 's2b', 's3a', 's3b', 's4a', 's4b', 's5a', 's5b', 's6a', 's6b', 's7a', 's7b', 's8a', 's8b', 's9a', 's9b', 's10a', 's10b']

EDIT: as a one-liner:

all_combos = ["".join(map(str,x)) for x in itertools.product(['s'], range(1, 11), ['a', 'b'])]

EDIT 2: as pointed out in James' answer, we can change our listed string element in the product call to just strings, and itertools will still be able to iterate over them, selecting characters from each:

all_combos = ["".join(map(str,x)) for x in itertools.product('s', range(1, 11), 'ab')]

4 Comments

Great! itertools.product is a nice example!
Is it possible to simplify ['a', 'b'] to 'ab', as in the answer of James?
@setempler Why don't you try it?
@setempler @StefanPochmann I've updated it to include this - ditto the 's', which doesn't really need to be a list here.
1

How about:

def func(prefix,suffixes,size):
    k = len(suffixes)
    return [prefix+str(n/k+1)+suffixes[n%k] for n in range(size*k)]

# usage example:
print func('s',['a','b'],10)

This way you can alternate as many suffixes as you want.

And of course, each one of the suffixes can be as long as you want.

1 Comment

A function was not my intention to use, but the return statement clearly yields an interesting approach to generalise the method.
0

You can use a double-list comprehension, where you iterate on number and suffix. You don't need to load any

Below is a lambda function that takes 3 parameters, a prefix, a number of iterations, and a list of suffixes

foo = lambda prefix,n,suffix: list(prefix+str(i)+s for s in suffix for i in range(n))

You can use it like this

foo('p',10,'abc')

Or like that, if your suffixes have more than one letter

foo('p',10,('a','bc','de'))

1 Comment

lambda is for creating anonymous functions, so it's generally considered bad style to bind a lambda to a name. If you want to write a named function you should use the proper def syntax.
0

For maximum versatility I would do this as a generator. That way you can either create a list, or just produce the sequence items as they are needed.

Here's code that runs on Python 2 or Python 3.

def psrange(prefix, suffix, high):
    return ('%s%d%s' % (prefix, i, s) for i in range(1, 1 + high) for s in suffix)

res = list(psrange('s', ('a', 'b'), 10))
print(res)

for s in psrange('x', 'abc', 3):
    print(s)

output

['s1a', 's1b', 's2a', 's2b', 's3a', 's3b', 's4a', 's4b', 's5a', 's5b', 's6a', 's6b', 's7a', 's7b', 's8a', 's8b', 's9a', 's9b', 's10a', 's10b']
x1a
x1b
x1c
x2a
x2b
x2c
x3a
x3b
x3c

Comments

Your Answer

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.