3

I am trying to append elements from a multi-dimensional list into a 2nd multi-dimensional list. Here is the code I wrote -

my_list = [[['b', ['a'], 'c'], ['d', ['a', 'b'], 'e']], 
           [['j', ['a', 'f']], ['q', 't']]]
ref_list = [[['q', 'w', 't'], ['y', 'u']], 
            [['s', 'o'], ['p', 'k', 'l']]]

newlist = []
for num, i in enumerate(my_list): 
  small_list = [] 
  for num_1, j in enumerate(i): 
    semilist = []
    for k in j:        
      if isinstance(k, list):      
        onelist = []
        for a in k:
          for ii in ref_list[num][num_1]:
            onelist.append(ii)           
        semilist.append(onelist)
      else:
        semilist.append(k)
    small_list.append(semilist)
  newlist.append(small_list)
      
print(newlist)

The output I am getting is -

[[['b', ['q', 'w', 't'], 'c'], ['d', ['y', 'u', 'y', 'u'], 'e']], [['j', ['s', 'o', 's', 'o']], ['q', 't']]]

The output I am looking for is of sort -

[[['b', ['q', 'w', 't'], 'c'], ['d', ['y', 'u'], 'e']], [['j', ['s', 'o']], ['p', 'k', 'l']]]

I want to replace elements of innermost list of "my_list" with the elements of the "ref_list".

2 Answers2

1

Try:

ref_list_flat = [l for sublist in ref_list for l in sublist]

for i, l1 in enumerate(my_list):
    for j, l2 in enumerate(l1):
        #check if this is the innermost list
        if not any(isinstance(l3, list) for l3 in l2):
            my_list[i][j] = ref_list_flat.pop(0)
        else:
            for k, l3 in enumerate(l2):
                if isinstance(l3, list):
                    my_list[i][j][k] = ref_list_flat.pop(0)

>>> my_list
[[['b', ['q', 'w', 't'], 'c'], ['d', ['y', 'u'], 'e']],
 [['j', ['s', 'o']], ['p', 'k', 'l']]]
not_speshal
  • 22,093
  • 2
  • 15
  • 30
0

Try:

my_list = [
    [["b", ["a"], "c"], ["d", ["a", "b"], "e"]],
    [["j", ["a", "f"]], ["q", "t"]],
]

ref_list = [[["q", "w", "t"], ["y", "u"]], [["s", "o"], ["p", "k", "l"]]]


for a, b in zip(my_list, ref_list):
    for i, subl in enumerate(a):
        for ii, v in enumerate(subl):
            if isinstance(v, list):
                subl[ii] = b[i]
                break
        else:
            a[i] = b[i]

print(my_list)

Prints:

[
    [["b", ["q", "w", "t"], "c"], ["d", ["y", "u"], "e"]],
    [["j", ["s", "o"]], ["p", "k", "l"]],
]

EDIT: To append elements from 2nd list instead replacing:

my_list = [
    [["b", ["a"], "c"], ["d", ["a", "b"], "e"]],
    [["j", ["a", "f"]], ["q", "t"]],
]

ref_list = [[["q", "w", "t"], ["y", "u"]], [["s", "o"], ["p", "k", "l"]]]


for a, b in zip(my_list, ref_list):
    for i, subl in enumerate(a):
        for ii, v in enumerate(subl):
            if isinstance(v, list):
                subl[ii].extend(b[i])
                break
        else:
            a[i].extend(b[i])

print(my_list)

Prints:

[
    [["b", ["a", "q", "w", "t"], "c"], ["d", ["a", "b", "y", "u"], "e"]],
    [["j", ["a", "f", "s", "o"]], ["q", "t", "p", "k", "l"]],
]

EDIT2: To add elements of 2nd list at the beginning of first list:

my_list = [
    [["b", ["a"], "c"], ["d", ["a", "b"], "e"]],
    [["j", ["a", "f"]], ["q", "t"]],
]

ref_list = [[["q", "w", "t"], ["y", "u"]], [["s", "o"], ["p", "k", "l"]]]


for a, b in zip(my_list, ref_list):
    for i, subl in enumerate(a):
        for ii, v in enumerate(subl):
            if isinstance(v, list):
                subl[ii] = b[i] + subl[ii]
                break
        else:
            a[i] = b[i] + a[i]

print(my_list)

Prints:

[
    [["b", ["q", "w", "t", "a"], "c"], ["d", ["y", "u", "a", "b"], "e"]],
    [["j", ["s", "o", "a", "f"]], ["p", "k", "l", "q", "t"]],
]
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • could you please explain/add comments to the code. It works but I am unable to understand it. The logic seems pretty complex for me(I am a beginner in Python). The else clause doesn't match the outer if clause. What's that else for? Also what does else clause do in this case? –  Jul 26 '21 at 19:38
  • 1
    @KatrinaMarrie Thats `for-else` statement. The block after `else` is executed, when `break` isn't called in inner `for`. It's not well known feature in Python, but it exists. – Andrej Kesely Jul 26 '21 at 19:39
  • what if I want to append the elements of 2nd list into inner linst of 1st list instead of replacing them. I am trying ```for a, b in zip(my_list, ref_list): for i, subl in enumerate(a): for ii, v in enumerate(subl): if isinstance(v, list): for j in b[i]: v.append(j) break else: a[i] = b[i]``` –  Jul 26 '21 at 19:45
  • This does not seem to work as the output I am getting is - ```[[['b', ['a', 'q', 'w', 't'], 'c'], ['d', ['a', 'b', 'y', 'u'], 'e']], [['j', ['a', 'f', 's', 'o']], ['p', 'k', 'l']]]``` –  Jul 26 '21 at 19:47
  • Could you please help me debug why my method is not appending elements only in the last list of list one. It seems to work fine for rest of the earlier elements. –  Jul 26 '21 at 19:51
  • 1
    @KatrinaMarrie You need to change the `a[i] = b[i]` after the `else:` too. – Andrej Kesely Jul 26 '21 at 19:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235314/discussion-between-katrina-marrie-and-andrej-kesely). –  Jul 26 '21 at 20:55
  • one last question. What if I want to add the elements of 1st list in the end. Here you used extend that will add elements of the 2nd list in the end. What if I want it the other way. Could you please help me to do that. –  Jul 26 '21 at 20:57