4

I have a list consisting of a repeating patterns i.e.

list=['a','1','first','b','2','second','c','3','third','4','d','fourth']`

I am not sure how long this list will be, it could be fairly long, but I want to create list of the repeating patters i.e. along with populated names

list_1=['a','1','first']
list_2=['b','2','second']
list_3=['c','3','third']
..... etc

What is the best, basic code (not requiring import of modules) that I can use to achieve this?

user88720
  • 322
  • 6
  • 14

2 Answers2

9

You can get the chunks using zip():

>>> lst = ['a','1','first','b','2','second','c','3','third','4','d','fourth']
>>> list(zip(*[iter(lst)]*3))
[('a', '1', 'first'), ('b', '2', 'second'), ('c', '3', 'third'), ('4', 'd', 'fourth')]

Using zip() avoids creating intermediate lists, which could be important if you have long lists.

zip(*[iter(lst)]*3) could be rewritten:

i = iter(lst)   # Create iterable from list
zip(i, i, i)    # zip the iterable 3 times, giving chunks of the original list in 3

But the former, while a little more cryptic, is more general.

If you need names for this lists then I would suggest using a dictionary:

>>> d = {'list_{}'.format(i): e for i, e in enumerate(zip(*[iter(lst)]*3), 1)}
>>> d
{'list_1': ('a', '1', 'first'),
 'list_2': ('b', '2', 'second'),
 'list_3': ('c', '3', 'third'),
 'list_4': ('4', 'd', 'fourth')}
>>> d['list_2']
('b', '2', 'second')
AChampion
  • 29,683
  • 4
  • 59
  • 75
  • `zip(*[iter(l)]*3)` this is a nice incantation, but this answer would be greatly improved if you were to explain what's happening here as it's clear as regex to a novice. – Jon Kiparsky May 22 '17 at 04:49
  • This is also much better than the original naive zip solution in that it can be generalized to chunks of any desired size. – Jon Kiparsky May 22 '17 at 04:51
  • 2
    There is a subtle point here. To understand this more precisely, you need to know that `[iter(lst)] * 3` returns a list of three references to THE SAME OBJECT. We then do a bit of a sleight of hand: we use the `*` operator to pass these objects to the `zip` function. The `zip` function forces evaluation of this single iterator, in groups of three, which happens one at a time from left to right, until the iterator runs out of items to iterate. – Jon Kiparsky May 22 '17 at 05:17
  • Strictly speaking, the call to `list` in `list(zip(*[iter(lst)]*3))` is gratuitous, since `zip` already returns a list. – Jon Kiparsky May 22 '17 at 05:20
  • 4
    `zip()` does not return a list in Py3 – AChampion May 22 '17 at 05:22
  • Ah, good point. So omitting the `list` in py3 makes this nicely lazy? Better and better! – Jon Kiparsky May 22 '17 at 05:40
  • Ah sorry guys, this is for Python 2.7. Will this still work? Also, is this the exact code I use? What do the >>> symbols mean? – user88720 May 22 '17 at 05:56
  • @user88720 Yes, this will work fine in either 2 or 3. The `>>>` symbols indicate that we're looking at a python shell session – Jon Kiparsky May 22 '17 at 06:00
  • To be more precise: if you define a function `chunkify(lst, n)` to return `zip(*[iter(l)]*3)`, you can then use `chunkify` to break a list `lst` into chunks of length `n`. – Jon Kiparsky May 22 '17 at 06:02
  • Oh right, thank you. I just realised though, the list that I am using is a combination of three other lists, I shouldn't have combined these in the first place. If I had three lists of all the same length, how could I achieve the same result as this (pull the first item from the first list and combine it with the first item from the second and third list, and so on) – user88720 May 22 '17 at 06:04
  • `zip(list1, list2, list3)` but you should really ask a different question. – AChampion May 22 '17 at 06:07
  • `zip(l1, l2, l3)` should do the work. If the lists turn out not to be of the same length, the resulting zip will have the length of the shortest list and excess elements in the longer lists will be ignored – Jon Kiparsky May 22 '17 at 06:08
  • @AChampion I think that question would be immediately deleted as a dupe :) – Jon Kiparsky May 22 '17 at 06:08
5

Try this

chunks = [data[x:x+3] for x in xrange(0, len(data), 3)]

It will make sublists with 3 items

Abdul Kawee
  • 2,687
  • 1
  • 14
  • 26