Generating a random subsequence

Alex Martelli aleax at aleax.it
Tue Jan 8 10:54:15 EST 2002


"Martin v. Loewis" <martin at v.loewis.de> wrote in message
news:m3n0zpivp9.fsf at mira.informatik.hu-berlin.de...
> Tom Bryan <tbryan at python.net> writes:
>
> > def randomSubseq( seq, length ):
>
> What would be wrong with
>
>       return random.shuffle(seq[:])[:length]

random.shuffle takes a MUTABLE sequence (typically a list),
shuffles it in-place, and returns None.  Thus, this code
would not work.


> I don't see the value of shuffling the indices.

I've already posted a version that shuffles a temp=list(seq)
instead (a tiny bit more direct, I think).  But returning a
result of the same type as seq (e.g. a string when called
as randomSubseq("weltanshaung",6)) does requiring slightly
more delicate handling than just returning a list would.

It's unfortunate that there's no smooth and seamless way to
make a sequence-of-arbitrary-type except by a loop such as
those in Tom's original solution or my variation thereon.

Alas, type(seq)(temp[:length]) doesn't work well when seq
is a string.  Maybe something like:

    temp = list(seq)
    random.shuffle(temp)

    try:
        joiner = seq[0:0].join
        if not callable(joiner): raise AttributeError
    except AttributeError:
        joiner = type(seq)

    return joiner(temp[:length])

would be an acceptable way to avoid the loop (in Python
2.2, of course) -- it would work for seq being a list,
tuple, string, or Unicode object -- but it seems somewhat
obscure and potentially fragile.  Maybe just as a last-
ditch optimization, using instead the loop:

    result = seq[0:0]
    for item in temp[:length]: result += item

    return result

as the "normal" approach otherwise.


Alex






More information about the Python-list mailing list