[Assorted-commits] SF.net SVN: assorted:[1018] python-commons/trunk/src/commons/seqs.py
Brought to you by:
yangzhang
From: <yan...@us...> - 2008-10-14 03:35:43
|
Revision: 1018 http://assorted.svn.sourceforge.net/assorted/?rev=1018&view=rev Author: yangzhang Date: 2008-10-14 03:35:37 +0000 (Tue, 14 Oct 2008) Log Message: ----------- added span, group_as_subseqs; added unittests for span, group_as_subseqs Modified Paths: -------------- python-commons/trunk/src/commons/seqs.py Modified: python-commons/trunk/src/commons/seqs.py =================================================================== --- python-commons/trunk/src/commons/seqs.py 2008-10-14 03:34:36 UTC (rev 1017) +++ python-commons/trunk/src/commons/seqs.py 2008-10-14 03:35:37 UTC (rev 1018) @@ -1,6 +1,12 @@ # -*- mode: python; tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4; -*- # vim:ft=python:et:sw=4:ts=4 +""" +Sequences, streams, and generators. + +@var default_chunk_size: The default chunk size used by L{chunkify}. +""" + from __future__ import ( absolute_import, with_statement ) from cStringIO import StringIO @@ -8,15 +14,37 @@ from struct import pack, unpack from contextlib import closing from itertools import ( chain, count, ifilterfalse, islice, - izip, repeat, tee ) -from .log import warning + izip, repeat, tee, takewhile ) +from commons.log import warning -""" -Sequences, streams, and generators. +__all__ = ''' +default_chunk_size +read_pickle +read_pickles +safe_pickler +write_pickle +streamlen +chunkify +total +ClosedError +PersistentConsumedSeq +PersistentSeq +pairwise +argmax +argmin +all +concat +flatten +grouper +chunker +countstep +take +delimit +interleave +group_as_subseqs +span +'''.split() -@var default_chunk_size: The default chunk size used by L{chunkify}. -""" - default_chunk_size = 8192 def read_pickle( read, init = '', length_thresh = 100000 ): @@ -283,15 +311,6 @@ else: return min((fn(e), e) for e in sequence)[1] -def all(seq, pred=bool): - """ - Returns C{True} if C{pred(x) is True} for every element in the - iterable - """ - for elem in ifilterfalse(pred, seq): - return False - return True - def concat(listOfLists): return list(chain(*listOfLists)) @@ -364,3 +383,53 @@ # TODO not quite right def interleave(xs, ys): return concat(izip( xs, ys )) + +def span(pred, xs): + """ + Returns (successes, failures), where successes is the sequence of any + consecutive elements at the head of L{xs} that satisfy the predicate, and + second is everything else. + """ + xs = iter(xs) + first_failure = [] + def successes(): + for x in xs: + if not pred(x): + first_failure.append(x) + break + yield x + return list(successes()), chain(first_failure, xs) + +def group_as_subseqs(xs, key = lambda x: x): + """ + Takes a sequence and breaks it up into multiple subsequences, which are + groups keyed on L{key}. + """ + xs = iter(xs) + while True: + setfirst = False + for x in xs: + first = x + setfirst = True + break + if not setfirst: break # We've hit the end + firstkey = key(first) + successes, xs = span(lambda x: key(x) == firstkey, xs) + yield chain([first], successes) + +import unittest + +class test_seqs(unittest.TestCase): + def test_span(self): + xs,ys = span(lambda x: x < 5, range(10)) + self.assertEqual(list(xs), range(5)) + self.assertEqual(list(ys), range(5,10)) + def test_group(self): + a,b,c,d = group_as_subseqs(range(10), lambda x: x / 3) + self.assertEqual(list(a), range(0,3)) + self.assertEqual(list(b), range(3,6)) + self.assertEqual(list(c), range(6,9)) + self.assertEqual(list(d), range(9,10)) + +if __name__ == '__main__': + unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |