Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!goblin3!goblin2!goblin.stu.neva.ru!newsfeed1.swip.net!uio.no!news.tele.dk!news.tele.dk!small.news.tele.dk!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.002 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'output': 0.05; 'follows.': 0.09; 'iterate': 0.09; 'received:80.91': 0.09; 'received:80.91.229': 0.09; 'received:gmane.org': 0.09; 'received:list': 0.09; 'sequences.': 0.09; 'def': 0.12; 'jan': 0.12; 'first:': 0.16; 'iterable': 0.16; 'iterables': 0.16; 'iterator': 0.16; 'itertools': 0.16; 'manifest': 0.16; 'received:80.91.229.3': 0.16; 'received:plane.gmane.org': 0.16; 'reedy': 0.16; 'subject:Converting': 0.16; 'successive': 0.16; 'unchanged': 0.16; 'elements': 0.16; 'wrote:': 0.18; 'producing': 0.19; 'version.': 0.19; 'input': 0.22; 'import': 0.22; 'header :User-Agent:1': 0.23; 'oriented': 0.24; 'passes': 0.24; 'typical': 0.24; 'question': 0.24; 'header:X-Complaints-To:1': 0.27; 'header :In-Reply-To:1': 0.27; 'subject:list': 0.30; 'usually': 0.31; 'assert': 0.31; 'omitted': 0.31; 'lists': 0.32; 'figure': 0.32; 'convert': 0.35; 'subject:lists': 0.35; 'but': 0.35; 'there': 0.35; 'yield': 0.36; 'list': 0.37; 'to:addr:python-list': 0.38; 'list,': 0.38; 'pm,': 0.38; 'to:addr:python.org': 0.39; 'received:org': 0.40; 'how': 0.40; 'new': 0.61; 'received:173': 0.61; 'first': 0.61; 'here': 0.66; 'products': 0.71; '102': 0.84; 'email name:steve': 0.84; 'filtered': 0.84; 'how.': 0.84; 'omission': 0.84; 'received:fios.verizon.net': 0.84; 'wanted,': 0.84 X-Injected-Via-Gmane: http://gmane.org/ To: python-list@python.org From: Terry Reedy Subject: Re: Converting a list of lists to a single list Date: Wed, 24 Jul 2013 11:56:30 -0400 References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Gmane-NNTP-Posting-Host: pool-173-75-251-66.phlapa.fios.verizon.net User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/20130620 Thunderbird/17.0.7 In-Reply-To: X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 66 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1374681415 news.xs4all.nl 15971 [2001:888:2000:d::a6]:50401 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:51144 On 7/23/2013 7:02 PM, Terry Reedy wrote: > On 7/23/2013 5:52 PM, steve@divillo.com wrote: >> I think that itertools may be able to do what I want but I have not >> been able to figure out how. What you want is a flattened product with unchanged components of the successive products omitted in the flattening. The omission is the difficulty. > A recursive generator suffices. But see below for how to use itertools.product. >> I want to convert an arbitrary number of lists with an arbitrary >> number of elements in each list into a single list as follows. While others answered the Python2-oriented question ("How do I produce a list from a list of lists"), I answered the Python-3 oriented question of how to produce an iterator from an iterable of iterables. This scales better to an input with lots of long sequences. There is usually no need to manifest the output as a list, as the typical use of the list will be to iterate it. > def crossflat(lofl): > if lofl: > first = lofl.pop(0) > for o in first: > yield o > yield from crossflat(lofl.copy()) > > A0, A1, A2 = 100, 101, 102 > B0, B1, B2 = 10, 11, 12 > C0, C1, C2 = 0, 1, 2 > LL = [[A0, A1, A2], [B0, B1, B2], [C0, C1, C2]] > cfLL = list(crossflat(LL)) > print(cfLL) > assert cfLL == [ > A0, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2, > A1, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2, > A2, B0, C0, C1, C2, B1, C0, C1, C2, B2, C0, C1, C2] > > passes Here is filtered flattened product version. I think it clumsier than directly producing the items wanted, but it is good to know of this approach as a backup. from itertools import product def flatprod(iofi): # iterable of iterables lofi = list(iofi) now = [object()] * len(lofi) for new in product(*lofi): i = 0 while now[i] == new[i]: i += 1 yield from new[i:] now = new cfLL = list(flatprod(LL)) Same assert as before passes. -- Terry Jan Reedy