switch recipe?

Mark McEahern marklists at mceahern.com
Mon Jul 15 15:31:23 EDT 2002


I want to thank everyone who posted to this thread.  I've gotten many
excellent suggestions.  The following demo presents all the distinct
variations I culled from the thread.  I like Emile's suggestion of the name
cycler, but I didn't use it in this demo--I think partly because for better
or worse alternator has lodged itself in my brain.

Cheers,

// mark

#! /usr/bin/env python

from __future__ import generators
import unittest

def weave(setn, setm):
    """Return a generator that iterates over setn and setm until setn is
    exhausted.  If setn is larger than setm, cycle over setm.
    """
    m = len(setm)
    if not setn or not setm:
        raise ValueError, "Weaved sets cannot be empty"
    for i in range(len(setn)):
        yield setn[i], setm[i%m]

def finite_alternator(length, *args):
    """Return a finite repeating alternator for args."""
    c = 0
    while args and c < length:
        for a in args:
            yield a
            c += 1
            if c >= length:
                break

def take(n, it):
    """Return n elements from the unbounded iterator."""
    for j in xrange(n):
        yield it.next()

def repeating_alternator(*args):
    """Return a repeating alternator for args."""
    while args:
        for a in args:
            yield a

def weave_items(iterator, alternator, weave_item):
    """Iterate over iterator, applying weave_item to each item with its
    pair in alternator.
    """
    for item in iterator:
        yield weave_item(item, alternator.next())

def color_item(item, color):
    template = "<%(color)s>%(item)s</%(color)s>"
    return template % locals()

class test(unittest.TestCase):

    def setUp(self):
        self.colors = ("red", "orange", "yellow", "green", "blue", "indigo",
                       "violet")
        self.expected = ['<red>0</red>',
                         '<orange>1</orange>',
                         '<yellow>2</yellow>',
                         '<green>3</green>',
                         '<blue>4</blue>',
                         '<indigo>5</indigo>',
                         '<violet>6</violet>',
                         '<red>7</red>',
                         '<orange>8</orange>',
                         '<yellow>9</yellow>']
        self.length = 10

    def test_weave(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        generated = [color_item(x, y) for x, y in weave(range(length),
colors)]
        self.assertEquals(expected, generated)

    def test_zip(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        iterator = range(length)
        alternator = repeating_alternator(*colors)
        weaved = zip(iterator, alternator)
        generated = [color_item(x, y) for x, y in weaved]
        self.assertEquals(expected, generated)

    def test_list_comprehension(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        iterator = range(length)
        alternator = repeating_alternator(*colors)
        generated = [color_item(x, alternator.next()) for x in iterator]
        self.assertEquals(expected, generated)

    def test_map(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        iterator = range(length)
        alternator = finite_alternator(length, *colors)
        generated = map(color_item, iterator, alternator)
        self.assertEquals(expected, generated)

    def test_map2(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        iterator = range(length)
        alternator = repeating_alternator(*colors)
        generated = map(color_item, iterator, take(length, alternator))
        self.assertEquals(expected, generated)

    def test_weave_items(self):
        colors = self.colors
        length = self.length
        expected = self.expected

        iterator = range(length)
        alternator = repeating_alternator(*colors)
        generated = [x for x in weave_items(iterator, alternator,
color_item)]
        self.assertEquals(expected, generated)

    def test_empty(self):
        r = repeating_alternator()
        self.assertRaises(StopIteration, r.next)

if __name__ == "__main__":
    unittest.main()

-






More information about the Python-list mailing list