mmacheerpuppy mmacheerpuppy - 4 months ago 10
Python Question

Matching up iterables in lists, having significant difficulty

For a personal project I have three lists. One of these contains a set of arrays (l2) the size of which is always determined by a setting l2_size and always contains random members of l1. The next array, l3, on the other hand will always be a set of 0's of quantity len(l1).

This means...

l1 = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
l2 = [[3, 4, 5, 2, 4],[3, 5, 1, 2, 4], [4, 3, 2, 1, 5]]
l3 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]


I need to perform a search such that


  1. Beginning with l2[0] if the pointer l2[0] hits l2[0], search through l1 to find l1[i] == the first value of l2[0].

  2. Once the first value of l2[0] use l3 to assign its corresponding value.

  3. Since the size of the arrays in l2[0] are 5 members we are going to assign a corresponding value of 1 to l3 a maximum of five times. Once we have hit that target we're moving onto the next set l2[1].

  4. Once we are done with l2[0] (so on to l2[1]) we need to assign the next corresponding value, so 2, without over-writing the values in l3.



Illustration...

Imagine these are baseball scoring cards... I have l1 baseball cards in my deck. The compositions of baseball scoring cards I want in my hands are contained in l2. These cards will win me the game! In this case l2 = [1,2,3,4,5]. I'm a massive cheater and must find all l2 in l1 (cards for hands). Finding l2 in l1 I mark where they are using l3. I also use l3 to tell me which hand to put them in.

To be a valid solution we must uniquely pair up the values in l2 such that they are uniquely identified as values in l1 using l3. This would mean...

l1 = [1,2,3,4,5,1,2,3,4,5]
l2 = [[1,2,3,4,5],[1,2,3,4,5]]
l3 = [1,1,1,1,1,2,2,2,2,2]


Would be valid. But...

l1 = [1,2,3,4,5,1,2,3,4,5]
l2 = [[1,2,3,4,5],[1,2,3,4,5]]
l3 = [1,2,1,1,1,2,2,1,2,2]


Would be invalid because there is no hand in l2 containing [2,1,2,4,5] in any order.

Example

From l2[0] we are going to iterate through l1 over and over and pick up all the objects in l2[0] and sign them off to l3. This should then look like (by hand)...

l1 = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
l2 = [[3, 4, 5, 2, 4],[3, 5, 1, 2, 4], [4, 3, 2, 1, 5]]
l3 = [0,0,1,1,1,0,1,0,1,0,0,0,0,0,0]


The value 1 has been assigned in l3 since these are the first instances of the corresponding values we come across. We are done with l2[0] now because we have found all of its items in l1. The next job is l2[1]...

l1 = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
l2 = [[3, 4, 5, 2, 4],[3, 5, 1, 2, 4], [4, 3, 2, 1, 5]]
l3 = [2,2,1,1,1,0,1,0,1,0,0,0,2,2,2]


This is what I've cooked up but to no avail...

assignvar = 1
pos = 0
for x in l2:
for y in x:
for z in l1:
while userpos < len(l1):
if y == z:
l1[pos] = assignvar
while l2_size == pos:
assignvar += 1
l2_size = l2_size+l2_size #stops pos going out of range, changes assignvar to 2 (so appending the next set of l3 iterables to 2 .etc)
userpos = userpos+1


Really quite confounded how to approach this issue in my code. I feel like I have the right idea using the three for loops but I've been hitting this with my wrench for a while now and completely burned out.

Answer

get sublist first, then using sublist's element get l1's index. increase 1 for l3 element based on l1's index

l1 = [1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]
l2 = [[3, 4, 5, 2, 4],[3, 5, 1, 2, 4], [4, 3, 2, 1, 5]]
l3 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

def combinList( lst ):
    ''' put list of list together based on index
        for example:
        a = [1,3,5,7]
        b = [2,4,6,8]
        combined list should be [1,2,3,4,5,6,7,8] '''
    step = len(lst)
    res= [None]*len(  reduce(lambda x,y:x+y, lst))
    for i,item in enumerate(lst):
        res[i::step] = sorted(item)
    return res


for value,line in enumerate(l2):
    counter = 0 
    record = {} 
    # count how many time this element appeared 
    for i in line:
        record[ i -1 ] = record.get( i - 1,0) + 1
    newList = combinList( [ [ i for i,j in enumerate(l1) if item == j] for item in line ] )
    for idx in newList:
        # if this element of l3 hasn't been change and there is at least one associated element in l2,put the value to l3 and reduce the number of l2
        if not l3[idx] and record.get(idx%5,0):
            l3[idx] = value + 1
            counter+=1
            record[idx%5] = record[idx%5] -1
        if counter >=5:
            break 
    print l3
print l3

output:

#first iteration 
[0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
#second iteration 
[2, 1, 1, 1, 1, 0, 2, 2, 1, 2, 0, 0, 0, 2, 0]
#third iteration 
[2, 1, 1, 1, 1, 3, 2, 2, 1, 2, 0, 3, 3, 2, 3]
#final iteration 
[2, 1, 1, 1, 1, 3, 2, 2, 1, 2, 0, 3, 3, 2, 3]
Comments