This must have been asked before, but I\'m afraid I can\'t find the answer.
In R, I can write
paste0(\'s\', 1:10)
which returns a l
None of these answers generalizes to arbitrary numbers of arguments like paste
in R does. Here is a fairly faithful port of the original R function. The only thing to remember is that each element must be presented as a list, since character strings in R are actually just vectors of characters under the hood:
import itertools
def paste(*args, sep = ' ', collapse = None):
"""
Port of paste from R
Args:
*args: lists to be combined
sep: a string to separate the terms
collapse: an optional string to separate the results
Returns:
A list of combined results or a string of combined results if collapse is not None
"""
combs = list(itertools.product(*args))
out = [sep.join(str(j) for j in i) for i in combs]
if collapse is not None:
out = collapse.join(out)
return out
Usage:
paste (['s'], range(10), sep = '')
Out[62]: ['s0', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9']
paste (['s'], range(2), ['t'], range(3), sep = '')
Out[63]: ['s0t0', 's0t1', 's0t2', 's1t0', 's1t1', 's1t2']
paste (['s'], range(2), ['t'], range(3), sep = '', collapse = ':')
Out[64]: 's0t0:s0t1:s0t2:s1t0:s1t1:s1t2'
You can get paste0
by using currying:
from functools import partial
paste0 = partial(paste, sep = '')
This is a bit closer to R's paste (including it's quirk of recycling arguments with length other than 1:
def paste(*args, sep = " ", collapse = None):
l = [list(arg) if isinstance(arg, str) else arg if hasattr(arg, '__len__') else list(str(arg)) for arg in args]
l = list(itertools.islice((sep.join(parts) for parts in zip(*(itertools.cycle(map(str, e)) for e in l))), (max((len(x) for x in l)))))
if collapse is not None:
l = collapse.join(l)
return l
paste(["a", "b"], range(2), "!")
# ['a 0 !', 'b 1 !']
>>> ["s" + str(i) for i in xrange(1,11)]
['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10']
EDIT: range
works in both Python 2 and Python 3, but in Python 2 xrange
is a little more efficient potentially (it's a generator not a list). Thansk @ytu
The answer by cdyson37 is the most pythonic one; of course you can still use range
rather than xrange
in your case.
In Python2, you can also put more emphasis on functional style with something like:
map(lambda x: "s"+str(x), range(1,11))
>>> list(map('s{}'.format, range(1, 11)))
['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10']