Roman Toasov
Roman Toasov

Reputation: 821

Make this python loop algorithm shorter (mathematics invloved)

For sake of learning i opt for not using any additional libraries.

Goal of this algorithm to break lit lst into chunks 8 records each. And additionally load the values from dictionary dct for records of lst 1-8, 9-16, 17-24.

Trying to avoid unnecessary for loops when possible, i come up with this solution.

dct = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight'}

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

loop = 0
for record in lst:
    print(f'record id: {record:<10} dct id: {record-loop:<10} dct value: {dct.get(record - loop)}')


    if record % 8 == 0:
        loop += 8
        print('--- loop finished ---')

this output

record id: 1          dct id: 1          dct value: one
record id: 2          dct id: 2          dct value: two
record id: 3          dct id: 3          dct value: three
record id: 4          dct id: 4          dct value: four
record id: 5          dct id: 5          dct value: five
record id: 6          dct id: 6          dct value: six
record id: 7          dct id: 7          dct value: seven
record id: 8          dct id: 8          dct value: eight
--- loop finished ---
record id: 9          dct id: 1          dct value: one
record id: 10         dct id: 2          dct value: two
record id: 11         dct id: 3          dct value: three
record id: 12         dct id: 4          dct value: four
record id: 13         dct id: 5          dct value: five
record id: 14         dct id: 6          dct value: six
record id: 15         dct id: 7          dct value: seven
record id: 16         dct id: 8          dct value: eight
--- loop finished ---
record id: 17         dct id: 1          dct value: one
record id: 18         dct id: 2          dct value: two
record id: 19         dct id: 3          dct value: three
record id: 20         dct id: 4          dct value: four
record id: 21         dct id: 5          dct value: five
record id: 22         dct id: 6          dct value: six
record id: 23         dct id: 7          dct value: seven
record id: 24         dct id: 8          dct value: eight
--- loop finished ---

Can someone with more mathematical experience suggest how can i get rid of variable loop altogether along with this section

if record % 8 == 0:
    loop += 8

and instead use some mathematical formula instead of record - loop

If i am simply using dct.get(record % 8) i am getting wrong result since record % 8 produces this code

1 2 3 4 5 6 7 0    1 2 3 4 5 6 7 0    1 2 3 4 5 6 7 0

I need

1 2 3 4 5 6 7 8    1 2 3 4 5 6 7 8    1 2 3 4 5 6 7 8 

Of course i could use a barbaric fix like this ((record - 1) % 8) + 1 to make it work, but i am sure there's more clean and more readable way of doing it.

Upvotes: 0

Views: 80

Answers (5)

Suramuthu R
Suramuthu R

Reputation: 1896

Your code seems to be perfect. The only way I guess to reduce the loop is : to create a list with multiples of 8 say eight_mult, and providing a conditional statement like if record in eight_mult: print('--- loop finished ---').

dct = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight'}

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
eight_mult = [x*8 for x in range(1,4)]

loop = 0
for record in lst:
    print(f'record id: {record:<10} dct id: {record-loop:<10} dct value: {dct.get(record - loop)}')


    if record in eight_mult: print('--- loop finished ---')

Edit: If your intention is to reduce the size of the code, in the second line: Instead of listing out all the 24 numbers, you can simply declare like lst = [x for x in range(1,25)]

Upvotes: 1

Roman Toasov
Roman Toasov

Reputation: 821

After thinking about it a bit i simplified it like this instead of using confusing formula ((record - 1) % 8) + 1 i added index for lst using enumerate() so it start with 0 and then formula become (idx % 8) + 1 which is same as idx % 8 + 1 then i did not need anymore the variable loop.

print('--- loop finished ---') was there for debugging information only so i did remove it.

dct = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight'}

lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

for idx, record in enumerate(lst):
    print(f'{record % 8}  record id: {record:<10} dct id: {(idx % 8) + 1:<10} dct value: {dct.get((idx % 8) + 1)}')

Upvotes: 0

Dan Nagle
Dan Nagle

Reputation: 5425

The chunk size is the length of dct.keys(). Whenever the modulus is zero you want to use the chunk size as the key.

dct = {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight'}
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

chunk_size = len(dct)

for record in lst:
    mod_value = record % chunk_size
    key = mod_value if mod_value else chunk_size
    print(f'record id: {record:<10} dct id: {key:<10} dct value: {dct.get(key)}')

Upvotes: 1

Adon Bilivit
Adon Bilivit

Reputation: 27196

You could use a nested for loop. You don't need the lst list

dct = {
    1: "one",
    2: "two",
    3: "three",
    4: "four",
    5: "five",
    6: "six",
    7: "seven",
    8: "eight",
}

for i in range(0, 24, 8):
    for j in range(i+1, i+9):
        print(f'record id: {j:<10} dct id: {j-i:<10} dct value: {dct.get(j-i)}')
    print('--- loop finished ---')

Upvotes: 0

Marcel Wilson
Marcel Wilson

Reputation: 4572

I think you may have a misunderstanding about how loops work.

Each loop finishes at the bottom of the code block.

loop = 0
for record in lst:
    # code here
    loop += 1
    print('--- loop finished ---')

In the case of your lst, you're going to make 24 loops.

However, it would appear you're not looking for the loop number but rather a counter of 1-8.

counter = 1
for record in lst:
    value = dct.get(counter)
    print(f'{record =:<10} {counter = :<10} {value = }')
    if record % 8 == 0:
        counter = 1
    else:
        counter += 1
record = 1          counter = 1          value = 'one'
record = 2          counter = 2          value = 'two'
record = 3          counter = 3          value = 'three'
record = 4          counter = 4          value = 'four'
record = 5          counter = 5          value = 'five'
record = 6          counter = 6          value = 'six'
record = 7          counter = 7          value = 'seven'
record = 8          counter = 8          value = 'eight'
-- counter reset --
record = 9          counter = 1          value = 'one'
record = 10         counter = 2          value = 'two'
record = 11         counter = 3          value = 'three'
record = 12         counter = 4          value = 'four'
record = 13         counter = 5          value = 'five'
record = 14         counter = 6          value = 'six'
record = 15         counter = 7          value = 'seven'
record = 16         counter = 8          value = 'eight'
-- counter reset --
record = 17         counter = 1          value = 'one'
record = 18         counter = 2          value = 'two'
record = 19         counter = 3          value = 'three'
record = 20         counter = 4          value = 'four'
record = 21         counter = 5          value = 'five'
record = 22         counter = 6          value = 'six'
record = 23         counter = 7          value = 'seven'
record = 24         counter = 8          value = 'eight'
-- counter reset --

Upvotes: 0

Related Questions