Search code examples
pythonloopsnestedproductpython-itertools

Why itertools.product dosen't return key and value from a dictionary in sequence? Help pls


I have a situation that is as follows. A nested loop like this:

d = [{'val1': 1, 'val2':2}, {'val3': 3, 'val4':4}, {'val5': 5, 'val6':6}, {'val7': 7, 'val8':8}, {'val9': 9, 'val10':10}]

num = list(range(len(d))
new_list = []
for i in num:
  for k, v in d[i].items():
    new_list.append([k ,v])

The result will be this:

[['val1', 1],
 ['val2', 2],
 ['val3', 3],
 ['val4', 4],
 ['val5', 5],
 ['val6', 6],
 ['val7', 7],
 ['val8', 8],
 ['val9', 9],
 ['val10', 10]]

Bu need to find a way to summarize these loops, either using functions like Map and Filter, or with the Itertools.product I read that turns nested loops into a loop only. So I made this code:

new_list = []
for i, (k,v) in itertools.product(num, d[i].items()):
    new_list.append([k ,v])

And the result is this:

    [['val9', 9],
 ['val10', 10],
 ['val9', 9],
 ['val10', 10],
 ['val9', 9],
 ['val10', 10],
 ['val9', 9],
 ['val10', 10],
 ['val9', 9],
 ['val10', 10]]

So I wanted to know if there is any way for itertools.product to produce the same result as the code with nested loops, that is, the outputs are in sequence and not just repeating the last two values. If there is a solution with map or filter, it is also welcome.

Update

@BrokenBenchmark My problem is a little more complex, so can you helpe me? The problem is this:

d = [{'val1': 1, 'val2':2}, {'val3': 3, 'val4':4}, {'val5': 5, 'val6':6}, {'val7': 7, 'val8':8}, {'val9': 9, 'val10':10}]  
d2 = [{'val1': 1, 'val2':2}, {'val3': 3, 'val4':4}, {'val5': 5, 'val6':6}, {'val7': 7, 'val8':8}, {'val9': 9, 'val10':10}]  
num = list(range(len(d))
new_list = []  
for i in num:      
    for k_i, v_i in d[i].items():
          for j in num:              
              for k_j, v_j in d2[j].items():                  
                  new_list.append([k_i, k_j])

Do you have a solution for that? That can replace this nested loop for something that speed up the code.

The output that I need is lists with key from dict 1 along with all keys from dict 2 (I need to compare each key from dict 1 with each key from dict 2). The output should be this:

[['Key1_dict1', 'Key1_dict2'],
['Key1_dict1', 'Key2_dict2'],
['Key1_dict1', 'Key3_dict2'],
['Key1_dict1', 'Key4_dict2'],
['Key1_dict1', 'Key5_dict2'],
['Key1_dict1', 'Key6_dict2'],
['Key1_dict1', 'Key7_dict2'],
['Key1_dict1', 'Key8_dict2'],
['Key1_dict1', 'Key9_dict2'],
['Key1_dict1', 'Key10_dict2'],
['Key2_dict1', 'Key1_dict2'],
['Key2_dict1', 'Key2_dict2'],
['Key2_dict1', 'Key3_dict2'],
['Key2_dict1', 'Key4_dict2'],
['Key2_dict1', 'Key5_dict2'],
['Key2_dict1', 'Key6_dict2'],
['Key2_dict1', 'Key7_dict2'],
['Key2_dict1', 'Key8_dict2'],
['Key2_dict1', 'Key9_dict2'],
['Key2_dict1', 'Key10_dict2']]

And so on.


Solution

  • Solution #1:

            d = [{'val1': 1, 'val2':2}, {'val3': 3, 'val4':4}, {'val5': 5, 'val6':6}, {'val7': 7, 'val8':8}, {'val9': 9, 'val10':10}]  
            d2 = [{'val1': 1, 'val2':2}, {'val3': 3, 'val4':4}, {'val5': 5, 'val6':6}, {'val7': 7, 'val8':8}, {'val9': 9, 'val10':10}]
    
            new_list = [[k_i, k_j] for i in range(len(d)) for k_i, v_i in d[i].items() for j in range(len(d2)) for k_j, v_j in d2[j].items()]
    

    Output:

    [['val1', 'val1'], ['val1', 'val2'], ['val1', 'val3'], ['val1', 'val4'], ['val1', 'val5'], ['val1', 'val6'], ['val1', 'val7'], ['val1', 'val8'], ['val1', 'val9'], ['val1', 'val10'], ['val2', 'val1'], ['val2', 'val2'], ['val2', 'val3'], ['val2', 'val4'], ['val2', 'val5'], ['val2', 'val6'], ['val2', 'val7'], ['val2', 'val8'], ['val2', 'val9'], ['val2', 'val10'], ['val3', 'val1'], ['val3', 'val2'], ['val3', 'val3'], ['val3', 'val4'], ['val3', 'val5'], ['val3', 'val6'], ['val3', 'val7'], ['val3', 'val8'], ['val3', 'val9'], ['val3', 'val10'], ['val4', 'val1'], ['val4', 'val2'], ['val4', 'val3'], ['val4', 'val4'], ['val4', 'val5'], ['val4', 'val6'], ['val4', 'val7'], ['val4', 'val8'], ['val4', 'val9'], ['val4', 'val10'], ['val5', 'val1'], ['val5', 'val2'], ['val5', 'val3'], ['val5', 'val4'], ['val5', 'val5'], ['val5', 'val6'], ['val5', 'val7'], ['val5', 'val8'], ['val5', 'val9'], ['val5', 'val10'], ['val6', 'val1'], ['val6', 'val2'], ['val6', 'val3'], ['val6', 'val4'], ['val6', 'val5'], ['va...
    
    

    Solution # 2:

            k, k2 = chain(*[m.keys() for m in d]), chain(*[m.keys() for m in d2])
            new_list_of_tuples = list(product(k, k2)) # if tuples are OK as key pairs
            new_list = [[*x] for x in product(k, k2)] # if you need lists as key pairs