I had two lists and I want to map them to each other, but one list contains more than 1 elements. so i zip them together, but it is not working properly

the list looks like this

a = ['TEMP', 'TEMP,PRE', 'TEMP,HUM,RAN', 'HUM']
b = ['TEM', 'BAR', 'BAO', 'RAI']

i am trying to acheive like this

TEM.TEMP
BAR.TEMP
BAR.PRE
BAO.TEMP
BAO.HUM
BAO.RAN
RAI.HUM

I want to map every item of b to a, but in 'a' there are more values separated by ,

my code is as follow

import csv


mod1 = []
dev2 = []
d = {}
with open('/home/robi/Desktop/rob/device.csv', 'rb') as f:
next(f, None)
reader = csv.reader(f, delimiter=';')
for row in reader:
    mod1.append(row[0])
    dev2.append(row[1])

a = zip(dev2, mod1)
for it, key in a:
    print it + '.' + key

But I am getting results like this

BAO.TEMP,HUM,RAN
BAR.TEMP,PRE
RAI.HUM

so BAR and BAO are not mapped correctly. Can someone guide me to correct my mistake. I would be thankful

    
negative but why?. I would be happy to hear, so that in future I must be careful while asking questions – robbin 4 hours ago

5 Answers 5

zip works on list indices so it cannot recognize if there are more items in a specific item based on your criteria. You'll have to do some post-processing to build your end list, namely split the element from the first list by a comma and then combine each with the elements from the second list. Something like:

a = ['TEMP', 'TEMP,PRE', 'TEMP,HUM,RAN', 'HUM']
b = ['TEM', 'BAR', 'BAO', 'RAI']

c = ["%s.%s"%(e[1],i) for e in zip(a, b) for i in e[0].split(",")]
# ['TEM.TEMP', 'BAR.TEMP', 'BAR.PRE', 'BAO.TEMP', 'BAO.HUM', 'BAO.RAN', 'RAI.HUM']
    
thanks zwer for the help. your piece of code works fine , but JRG one looks simple to me and it also works. I cannot accept two answer, otherwise I would accept your one also. .but thank you so much for your help. – robbin 5 hours ago
    
@robbin - except that his answer is not correct, at least as long as your question is I want to map every item of b to a - his code will give you a list of combinations of a and b which includes things like BAR.RAN and that's not in your desired output list. If you wanted all combinations of items in a and b you should update your question to reflect that. – zwer 5 hours ago
    
yes I want to map every item of b to a. .wait i will check again. sorry my mistake. . – robbin 4 hours ago
    
you are correct. its my mistake . his code gave me combinations. .I will make an apology to him and will accept your answer cox your were the second i guess to answer and your solution works fine. – robbin 4 hours ago
    
'.'.join((e[1],i))is more readable to me than "%s.%s"%(e[1],i) – f5r5e5d 4 hours ago

Try this at the end:

a = zip(dev2, mod1)
for it, key in a:
    words = key.split(',')
    for word in words:
        print it + '.' + word
1  
thanks a lot for the help. your code works well but JRG respond first and his code also works fine that why i accept his answer. but thanks a lot for the help. – robbin 5 hours ago

Using list comprehension and join (assuming a and b has same length)

a = ['TEMP', 'TEMP,PRE', 'TEMP,HUM,RAN', 'HUM']
b = ['TEM', 'BAR', 'BAO', 'RAI']
length = len(a)

result = ['.'.join((b[index],sub_item) ) 
              for index in range(length) for sub_item in a[index].split(',')]

(This seems to take little less time than using zip)

Is this what you're lookin for?

 >>> [[(b[i], x) for x in a[i].split(',')] for i in range(len(a))]
 [[('TEM', 'TEMP')],
 [('BAR', 'TEMP'), ('BAR', 'PRE')],
 [('BAO', 'TEMP'), ('BAO', 'HUM'), ('BAO', 'RAN')],
 [('RAI', 'HUM')]]

Even though my answer wasn't good enough for you, here's a solution that would put it into strings like you seemed to want.

>>> reduce(lambda x, y: x + y, [['.'.join((b[i], x)) for x in a[i].split(',')] for i in range(len(a))])
['TEM.TEMP',
 'BAR.TEMP',
 'BAR.PRE',
 'BAO.TEMP',
 'BAO.HUM',
 'BAO.RAN',
 'RAI.HUM']

Sadly, no one will ever see this, but at least I will know how awesome I am... /s

Iterate over items in b as it doesn't have multiple keys in single key and then iterate over items in a and check if it contains delimiter , and split over it.

I have additionally added code to have unique combinations using set, if you want.

def getCombinations(a, b):
    combinations = []
    for bitem in b:
        for aitem in a:
            if ("," in aitem):
                for aitemInner in aitem.split(","):
                    combinations.append(bitem + "." + aitemInner)
            else:
                combinations.append(bitem + "." + aitem)
    ## Optional : if you want unique combinations of B and A
    unique = set(combinations)
    return unique

a = ['TEMP', 'TEMP,PRE', 'TEMP,HUM,RAN', 'HUM']
b = ['TEM', 'BAR', 'BAO', 'RAI']
combinations = getCombinations(a, b)
print("Keys in a          : " + str(len(a)))
print("Keys in b          : " + str(len(b)))
print("Total Combinations : " + str(len(combinations)))
print(combinations)

Sample Run

Keys in a          : 4
Keys in b          : 4
Total Combinations : 16
{'TEM.HUM', 'RAI.HUM', 'BAR.PRE', 'BAO.HUM', 'TEM.PRE', 'RAI.RAN', 'RAI.TEMP', 'BAR.HUM', 'RAI.PRE', 'BAO.PRE', 'BAR.RAN', 'BAO.RAN', 'TEM.TEMP', 'TEM.RAN', 'BAO.TEMP', 'BAR.TEMP'}

EDIT : Updating the solution with the requirement that it doesn't need all combinations but it needs mapping of elements in b with a.

Here also, I am using set if you need unique mappings else you can return combinations from the get1To1Mapping() method.

NOTE: I am getting the minimum size of both the list and only giving mapping for no. of elements as per minimum list to avoid exception.

def get1To1Mapping(a, b):
    combinations = []
    ## some might argue to iterate over len(b) but i would go for minimum
    ## of both the list to avoid exception
    for index in range(min(len(a), len(b))):
        if ("," in a[index]):
            for aitem in a[index].split(","):
                combinations.append(b[index] + "." + aitem)
        else:
            combinations.append(b[index] + "." + a[index])
    ## optional : if you want just unique mappings
    unique = set(combinations)
    return unique

a = ['TEMP', 'TEMP,PRE', 'TEMP,HUM,RAN', 'HUM']
b = ['TEM', 'BAR', 'BAO', 'RAI']
combinations = get1To1Mapping(a, b)
print("Keys in a          : " + str(len(a)))
print("Keys in b          : " + str(len(b)))
print("Total Combinations : " + str(len(combinations)))
print(combinations)

Sample Run

Keys in a          : 4
Keys in b          : 4
Total Combinations : 7
{'BAR.PRE', 'RAI.HUM', 'TEM.TEMP', 'BAO.TEMP', 'BAO.HUM', 'BAO.RAN', 'BAR.TEMP'}
    
np, glad to help – JRG 5 hours ago
    
No need to check before you split. – juanpa.arrivillaga 4 hours ago
    
@JRG accept my apology, i didn't check properly. your code has one problem that it gave me combination. but i am trying just to map every element in b to a. .I will accept zwer answer. i am very sorry and its my mistake. I hope you will understand – robbin 4 hours ago
    
no worries on accepting answer, I would like to correct my solution so it's workable for future references. Can you explain what you mean by mapping element in b to a, do you have expected output? – JRG 3 hours ago
    
@JRG thanks for accepting my apology. .yes the expected output is given in question also. but i am writing it here too. .TEM.TEMP, BAR.TEMP, BAR.PRE, BAO.TEMP, BAO.HUM, BAO.RAN, RAI.HUM – robbin 3 hours ago