0

Python: List comprehension list of lists

So far I have seen that list comprehension works really well for matrices and even tuple sublists:

x = [[1,2,3],[4,5,6],[7,8,9]]

yet I do not think I have seen a good solution to the uneven sublist situation:

x = [[[[34, 21], [20, 21],[24, 212],[20, 21],[16, 12],[840, 190],[-406, 188],[-410, 185]],[[220, 204],[229, 167],[234, 100],[231, 150],[236, 156],[232, 1362],[254, 196],[256, 962],[258, 878],[254, 776],[264, -50],[271, -410]],[[2326, 1984],[2412, 1958],[2540, 1896],[4506, 869]]]]

How would I run a function in a manner similar to list comprehension over the tuples that changes and replaces all of their values? Supposing the function to be used as the following:

def tuplFun(x1, y1):
    a = x1 / 2 * 30.0 - 80.0
    b = math.atan(math.sinh(math.pi * (1 - 2 * y1 / 4)))
    return (a, b)

Please pardon if I use the incorrect terminology since I am not a regular developer or programmer. This is a matter of understanding the limitations of list comprehensions and the proper way to address different scenarios that exist within data sets.

Thank you.

Aaron
  • 317
  • 4
  • 16
  • So you want a comprehension to build a list like the one in the question? What would be the construction logic behind the list? – Dani Mesejo Dec 08 '19 at 11:49
  • There is no transformation of the structuring of the data in question, instead only the values are updated or changed. The data originates from a graphics program, whereby we are seeing lines in vector form. For some reason, I think the unevenness of the sublists (individual line data) makes the application of comprehensions difficult. Possibly a for loop or recursion/loop combination to apply the function. – Aaron Dec 08 '19 at 13:51

1 Answers1

1

Ok, let's start working with 'the more difficult' x you have given:

x = [[[[34, 21], [20, 21],[24, 212],[20, 21],[16, 12],[840, 190],[-406, 188],[-410, 185]],[[220, 204],[229, 167],[234, 100],[231, 150],[236, 156],[232, 1362],[254, 196],[256, 962],[258, 878],[254, 776],[264, -50],[271, -410]],[[2326, 1984],[2412, 1958],[2540, 1896],[4506, 869]]]]

I will define another tupl2Fun(x1, y1) for the sake of simplicity because your tuplFun(x1, y1) is not defined for some x1, y1:

def tupl2Fun(x1, y1):
    a = x1 - 1
    b = y1 + 1
    return [a, b]

What you want is a nested list comprehension. There are two ways to do it:

def nested_list_comprehension1(x):
    #replaces every cell of x dynamically
    for a in x:
        for b in a:
            for c in b:
                c[0], c[1] = tupl2Fun(c[0], c[1])

def nested_list_comprehension2(x):
    #return copy of x replaced how you want
    return [[[[tupl2Fun(c[0], c[1]) for c in b] for b in a] for a in x]]

print('initial value of x is: \n', x)
nested_list_comprehension1(x)
print('after applying ''nested_list_comprehension1(x)'' new value of x is: \n', x)
print(nested_list_comprehension2(x))
print('the output of ''nested_list_comprehension2(x)'' is: \n', x)
print('current value of x is: \n', x)

You would also like to refuse doing three loops manually in case you don't know depth of your list. In this case use of recursive function is required:

def replacer(array):
    if type(array[0]) is not list:
        return tupl2Fun(array[0], array[1])
    else: return [replacer(n) for n in array]

    print('the output of ''replacer(x)'' is:')
    print(replacer(x))

This will check if first item of your list is another list and if it's not, apply your function. Otherwise, the same checks will be done for each item.

Output of replacer(x):

[[[[33, 22], [19, 22], [23, 213], [19, 22], [15, 13], [839, 191], [-407, 189], [-411, 186]], [[219, 205], [228, 168], [233, 101], [230, 151], [235, 157], [231, 1363], [253, 197], [255, 963], [257, 879], [253, 777], [263, -49], [270, -409]], [[2325, 1985], [2411, 1959], [2539, 1897], [4505, 870]]]]
mathfux
  • 5,759
  • 1
  • 14
  • 34