Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python process list elements in batches

I have sequence of played cards in a list. There were 4 players, so each four elements in the list represent a single trick. I have to process 4 cards together to find trick winner. I need to split the list four elements at a time. I am currently doing the following:

cardSequnce = [
    'D7', 'D8', 'DT', 'DA',
    'H2', 'H7', 'HK', 'H5',
    'H3', 'HT', 'HA', 'HQ',
    'H8', 'D2', 'H4', 'HJ',
    'D6', 'D3'
]
four_card = []
for index, card in enumerate(cardSequnce):
    if(index % 4 == 0):
        # process four_card
        four_card = []
    four_card.append(card)

I think that I can do better than this using power of python. Can I access 4 cards together in a loop? Can any one help me to make my code more Pythonic?

like image 689
avni hirpara Avatar asked Jul 14 '17 14:07

avni hirpara


People also ask

What is batch processing python?

Batch processing typically refers to processing a "batch" of files. The files are usually very similar such as DEMs or satellite images for a large area. The processing we'll look at here will work for a few files or thousands.

Can you split a list in Python?

To split the elements of a list in Python: Use a list comprehension to iterate over the list. On each iteration, call the split() method to split each string.


3 Answers

If you want to create lists of length of 4 from a list, this would do the trick:

[cardSequence[i:i + 4] for i in range(0, len(cardSequence), 4)]
like image 84
Hannu Avatar answered Nov 03 '22 07:11

Hannu


offset = 4
index = 0
while index < len(YourList):
       result = YourList[index:index+offset]
       index += offset
like image 33
pooya Avatar answered Nov 03 '22 06:11

pooya


You can make your code a bit nicer by iterating explicitly through groups of four instead of element-by-element. There are a couple of ways of doing this. The easiest would just be to increment the index by four:

card_sequence = ...
for index in range(0, len(cardSequence), 4):
    four_card = card_sequence[index:index + 4]
    # process four_card

This has the advantage of not calling the processing code on an empty four_card when index == 0, as your code does. Also, I would recommend sticking to one naming convention (underscores vs CamelCase). I picked the former since that is the generally recommended Python convention.

You can do a slightly more complicated version using the grouper recipe provided by the itertools documentation. The advantage of this approach is that it will probably scale better:

def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)
card_sequence = ...
for four_card in grouper(card_sequence, 4):
    four_card = list(four_card)
    # Process four_card

Keep in mind that this implementation of grouper is going to fill extra elements in the last group with None if your input sequence does not have a multiple of four elements. It also assumes that you consume all the elements of the group in each iteration (which you do in this case). For alternative implementations, see this wonderful answer.

like image 33
Mad Physicist Avatar answered Nov 03 '22 06:11

Mad Physicist