Re: Feature Proposal: Sequence .join method



On Fri, 30 Sep 2005 09:38:25 -0700, Michael Spencer <mahs@xxxxxxxxxxxxxxxxx> wrote:
Terry Reedy wrote:
"David Murmann" <david.murmann@xxxxxxxxxxxxxx> wrote in message
news:3q3pt9Fd7pklU1@xxxxxxxxxxxxxxxxx

def join(sep, seq):
   return reduce(lambda x, y: x + sep + y, seq, type(sep)())

damn, i wanted too much. Proper implementation:

def join(sep, seq):
   if len(seq):
       return reduce(lambda x, y: x + sep + y, seq)
   return type(sep)()

but still short enough


For general use, this is both too general and not general enough.

If len(seq) exists then seq is probably reiterable, in which case it may be
possible to determine the output length and preallocate to make the process
O(n) instead of O(n**2).  I believe str.join does this.  A user written
join for lists could also.  A tuple function could make a list first and
then tuple(it) at the end.

If seq is a general (non-empty) iterable, len(seq) may raise an exception
even though the reduce would work fine.

Terry J. Reedy



For the general iterable case, you could have something like this:

 >>> def interleave(sep, iterable):
 ...     it = iter(iterable)
 ...     next = it.next()
 ...     try:
 ...         while 1:
 ...             item = next
 ...             next = it.next()
 ...             yield item
 ...             yield sep
 ...     except StopIteration:
 ...         yield item
 ...
 >>> list(interleave(100,range(10)))
 [0, 100, 1, 100, 2, 100, 3, 100, 4, 100, 5, 100, 6, 100, 7, 100, 8, 100, 9]
 >>>

but I can't think of a use for it ;-)

I have this version:

   def interlace(x, i):
       """interlace(x, i) -> i0, x, i1, x, ..., x, iN
       """
       i = iter(i)
       try:
           yield i.next()
       except StopIteration:
           return
       for e in i:
           yield x
           yield e

And I use it for things like interleave(", ", ["foo", bar, "baz"]), where bar is not a string, but can be handled along with strings by a lower-level chunk of code.

Jp
.