0

I have two nested lists (list of lists) and one nested list of True/False (pattern) that I want to use to pick and choose items from two input lists to create a final list.

inputListTrue = [[1,1,1],[2,2,2],[3,3,3]]
inputListFalse = [[a,a,a],[b,b,b],[c,c,c]]
pattern = [[True, False, True],[True, True, True],[False, False, True]]

finalDesiredList = [[1,a,1],[2,2,2],[c,c,3]]

What is the most efficient way to create a definition that would work on any depth of nested lists....[[[],[]],[]] etc. I was looking for something really flexible unlike my initial thought of just iterating:

for i, j, k in zip(pattern, inputListTrue , inputListFalse ):
    for l,m,n in zip(i,j,k):
        if l:
            finalDesiredList .append(m)
        else:
            finalDesiredList .append(n)

This is only good for a list of lists and not for list of list of list etc. Ideas?

Mazdak
  • 105,000
  • 18
  • 159
  • 188
konrad
  • 3,544
  • 4
  • 36
  • 75
  • Perhaps [``filter()``](https://docs.python.org/2/library/functions.html#filter) would help. – pzp Apr 28 '15 at 15:33
  • Is the elements within lists always equal? – Mazdak Apr 28 '15 at 15:34
  • I don't understand your requirement for 'any depth of nested lists'. Could you give a full example? Perhaps [flattening the list of lists](http://stackoverflow.com/questions/952914/making-a-flat-list-out-of-list-of-lists-in-python) is something to look at. –  Apr 28 '15 at 15:37
  • @Kasra no, they will be a mix of things. Anywhere from strings to integers and maybe even other object types – konrad Apr 28 '15 at 15:37

3 Answers3

1

Here is a recursive method to do this for arbitrary nested sequences

def choose(first, second, value):
    if hasattr(first, '__iter__'):
        return [choose(i,j,k) for i,j,k in zip(first, second, value)]
    else:
        return first if value else second

Example

>>> inputListTrue = [[1,1,1],[2,2,2],[3,3,3]]
>>> inputListFalse = [['a','a','a'],['b','b','b'],['c','c','c']]
>>> pattern = [[True, False, True],[True, True, True],[False, False, True]]
>>> choose(inputListTrue, inputListFalse, pattern)
[[1, 'a', 1], [2, 2, 2], ['c', 'c', 3]]

This is assuming the sequences all have have the same dimensions.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
1

As a more general way you can use a recursion function :

def filt(pattern, inputListTrue , inputListFalse ,finalDesiredList=[]) :
      for i, j, k in zip(pattern, inputListTrue , inputListFalse ):
          temp=[]
          for l,m,n in zip(i,j,k):

              if isinstance (l,list):
                   return filt(i,j,k)
              else :
                 if l:
                      temp .append(m)
                 else :
                      temp .append(n)
          finalDesiredList.append(temp)
      return finalDesiredList



inputListTrue = [[1,1,1],[2,2,2],[3,3,3]]
inputListFalse = [['a','a','a'],['b','b','b'],['c','c','c']]
pattern = [[True, False, True],[True, True, True],[False, False, True]]

print filt(pattern, inputListTrue , inputListFalse)
[[1, 'a', 1], [2, 2, 2], ['c', 'c', 3]]
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • yes, this works but i will still need to add a check for whether its a flat list before i go into two subsequent "for loops". Otherwise it will throw an error on a flat list. – konrad Apr 28 '15 at 15:56
  • @konrad You didn't mentioned about that! i'll update the answer! – Mazdak Apr 28 '15 at 16:00
0
def filtFlat(pattern, inputListTrue, inputListFalse):
    result = []
    for i, j, k in zip(pattern, inputListTrue, inputListFalse):
        if i == False:
            result.append(k)
        else:
            result.append(j)
   return result

def filt(pattern, inputListTrue , inputListFalse ) :
    finalDesiredList=[]
    for i, j, k in zip(pattern, inputListTrue , inputListFalse ):
        temp=[]
        for l,m,n in zip(i,j,k):
            if isinstance (l,list):
                return filt(i,j,k)
            else:
                if l:
                    temp.append(m)
                else:
                    temp.append(n)
        finalDesiredList.append(temp)
    return finalDesiredList

I can always use the two definitions and do a check for a flat list:

if any(isinstance(item, list) for item in pattern):
konrad
  • 3,544
  • 4
  • 36
  • 75