Simpler way to get combinations and group them based on key values?

708
6
Jump to solution
01-30-2023 01:53 PM
RPGIS
by
Occasional Contributor III

Hi,

I wanted to see if anyone could help with figuring out if there is a simpler way to code what I have below. What I have below works fine but I wanted to see if there was a simpler way to write the code.

Fields, Grps = ['FieldA','FieldB','FieldC'], ['GroupA','GroupB','GroupC']
Main = [['DOG','CAT','HORSE'], ['HOUSE','BARN'], ['FIELDS', 'YARD'],['MOUSE','SNAKE','LIZARD','OTHER'],['AQUARIUM','GLASS TANK','SMALL CAGE'],
        ['HOUSE','APARTMENT','PET STORE'],['COW','PIG', 'SHEEP'], ['FIELDS','PASTURES'], ['BARN','FARM HOUSE','OTHER']]
MainDict = dict(zip([chr(i) for i in range(ord('A'),ord('A')+len(Main))], Main))
EstVOrder = [[i for i in [chr(i) for i in range(ord('A')+n,ord('A')+n+len(Fields))]] for n in range(0,len(Main),len(Main)//len(Fields))]
Main = dict(zip(Grps,[[[x,y,z] for x in MainDict[a] for y in MainDict[b] for z in MainDict[c]] for a,b,c in EstVOrder]))
print (Main)

 

I would also like to know if the code above is properly written.

0 Kudos
1 Solution

Accepted Solutions
JoshuaBixby
MVP Esteemed Contributor

After taking a longer look at your data and code, it seems you are trying to reinvent the product - itertools — Functions creating iterators for efficient looping wheel.  I can confidently state that any native Python code someone writes will not outperform the compiled functions in the itertools module.

from itertools import product
Fields, Grps = ['FieldA','FieldB','FieldC'], ['GroupA','GroupB','GroupC']
Main = [['DOG','CAT','HORSE'], ['HOUSE','BARN'], ['FIELDS', 'YARD'],['MOUSE','SNAKE','LIZARD','OTHER'],['AQUARIUM','GLASS TANK','SMALL CAGE'],
        ['HOUSE','APARTMENT','PET STORE'],['COW','PIG', 'SHEEP'], ['FIELDS','PASTURES'], ['BARN','FARM HOUSE','OTHER']]
Main = {g:list(product(*Main[i*3:i*3+3])) for i,g in enumerate(Grps)}
print(Main)

 

View solution in original post

0 Kudos
6 Replies
by Anonymous User
Not applicable

We code for people, so keep it zen:

import this

...

Beautiful is better than ugly.

Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.

...

If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.

Think I'd add some comments of the what the list comprehensions are creating to add clarity.

# MainDict = {'A': ['DOG', 'CAT', 'HORSE'], 'B': ['HOUSE', 'BARN'], ...}

# Main = {'GroupA': [['DOG', 'HOUSE', 'FIELDS'], ..., ['HORSE', 'BARN', 'YARD']], ...}

I suspect Pandas would make short work of creating your final dictionary in a much more elegant way.

 

0 Kudos
RPGIS
by
Occasional Contributor III

Thanks @Anonymous User,

The code itself was to see if there was a way to create a list of lists with combinations of values that were the same length and order as the fields. I was also trying to do it with the fewest lines of code possible to see if it could be done. I know the code itself is not that pretty, beautiful, or easy to read/understand, but my goal was to see if I could achieve a complex task with the fewest lines of code.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Code golf might be a fun exercise, but it usually leads to challenging code to read and even poorer performing code at times. 

0 Kudos
RPGIS
by
Occasional Contributor III

Thanks @JoshuaBixby,

I thought of it as a fun exercise to see if I could utilize it for smaller scripts since it gave me the opportunity to try and test what I can do. I was not aware of the performance issues regarding how the code is written, so I will have a to run a few test scripts to see how significant the difference is.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

After taking a longer look at your data and code, it seems you are trying to reinvent the product - itertools — Functions creating iterators for efficient looping wheel.  I can confidently state that any native Python code someone writes will not outperform the compiled functions in the itertools module.

from itertools import product
Fields, Grps = ['FieldA','FieldB','FieldC'], ['GroupA','GroupB','GroupC']
Main = [['DOG','CAT','HORSE'], ['HOUSE','BARN'], ['FIELDS', 'YARD'],['MOUSE','SNAKE','LIZARD','OTHER'],['AQUARIUM','GLASS TANK','SMALL CAGE'],
        ['HOUSE','APARTMENT','PET STORE'],['COW','PIG', 'SHEEP'], ['FIELDS','PASTURES'], ['BARN','FARM HOUSE','OTHER']]
Main = {g:list(product(*Main[i*3:i*3+3])) for i,g in enumerate(Grps)}
print(Main)

 

0 Kudos
RPGIS
by
Occasional Contributor III

Thanks @JoshuaBixby

I didn't even realize that I had replicated an existing function. I knew of the itertools, but from examples I have seen online, I thought it might be limited, or there were other ways to achieve the same thing without importing another module. I will research more into these and other python modules to see if some of the code that I have written can be simplified using an existing module.

0 Kudos