Storing values from list in matrix like form

Question:

I have the following list L for which I’m trying to store the values in "rows" logic locating each value
in the position given by dictionary HeadersPositions.

This is my current code, for which I tried while element[0] != "V": in order to change to a next row after get the last header that is V for each "row", but I got an infinite loop, then I changed to if element[0] != "V": in order to control when to switch to next row but is only storing in list row, the first position of header B

L = [
    ['B', 3], 
    ['T', 0], 
    ['N', 5], 
    ['V', 2], 
    ['N', 1], 
    ['V', 4],
    ['B', 7], 
    ['T', 2], 
    ['N', 9], 
    ['V', 1], 
    ['B', 1], 
    ['N', 8], 
    ['V', 3]
]

HeadersPositions = {'B': 0, 'T': 1, 'N': 2, 'V': 3}

rows = []
row=[None]*len(HeadersPositions)
for element in L:
    if element[0] != "V":
        row.insert(HeadersPositions[element[0]], element[1])
    rows.append(row)

My desired output is

Out = [
        [3,0,5,2], 
        [none,none,1,4], 
        [7,2,9,1], 
        [1,none,8,3],         
    ]      

Seen like table would be like this:

B   T   N   V
3   0   5   2
        1   4
7   2   9   1  
1       8   3
Asked By: Rasec Malkic

||

Answers:

Having renamed L to data (since L is a capital letter and l would also not be a recommended variable name):

data = [
    ['B', 3], 
    ['T', 0], 
    ['N', 5], 
    ['V', 2], 
    ['N', 1], 
    ['V', 4],
    ['B', 7], 
    ['T', 2], 
    ['N', 9], 
    ['V', 1], 
    ['B', 1], 
    ['N', 8], 
    ['V', 3]
]

headers_positions= {'B': 0, 'T': 1, 'N': 2, 'V': 3}
rows = []
while data:
    rows.append([
        data.pop(0)[1] if data and data[0][0] == h else None
        for h in headers_positions.keys()
    ])

print(rows)

Output:

[[3, 0, 5, 2], [None, None, 1, 4], [7, 2, 9, 1], [1, None, 8, 3]]

Note: this is ignoring the values of the HeadersPositions, and you should probably use a list there if that’s OK.

Otherwise:

headers_positions = {'B': 0, 'T': 1, 'N': 2, 'V': 3}
headers = [k for k, v in sorted(headers_positions.items(), key=lambda h: h[1])]
rows = []
while data:
    rows.append([
        data.pop(0)[1] if data and data[0][0] == h else None
        for h in headers
    ])

Edit: You asked for some explanation of how it actually works.

On the outside:

while data:
    rows.append([
        ...
    ])

As long as data is not empty, the loop will continue to add new rows. Note that data itself is being emptied out. If you need data to remain unchanged, you could instead:

c_data = list(data)
while c_data:
    rows.append([
        ...
    ])

That would create a copy of data, and you’d use c_data inside the loop.

The lists that are being added as rows:

    [
        data.pop(0)[1] if data and data[0][0] == h else None
        for h in headers_positions.keys()
    ]

This:

  • pops the first element from data, if there’s still data left (if data) and the first element matches the current header (data[0][0] == h). data.pop(0) removes the first element from data and only the value [1] is then used to populate the list.
  • if there’s no data left, or the first value left in data doesn’t match the header, it adds a None to the list instead
  • and it does so for every header in the list of headers in order.

So, on the first row, it finds a value for B, T, N, and V in order, so they all get popped and added. On the second row, it doesn’t find the value for B at the start, so it adds None, doesn’t find T either so another None is added, but then it does find N at the start, so it pops 1 into the list, etc.

This way to construct a list for each row is called a ‘list comprehension’. And while data and if data make use of the truthiness of a list, an empty list is False, while a non-empty list is True.

Answered By: Grismar

You can try this primitive solution

def function(L, keylist):
    final_out = []
    out = []
    for i in range(len(L)):
        k = len(out)
        key = L[i][0]
        value = L[i][1]

        while key != keylist[k]:
            out.append(None)
            k = k + 1

        out.append(value)
        if len(out) == len(keylist):
            final_out.append(out)
            out = []

    return final_out

results:

keylist = ["B", "T", "N", "V"]
print(function(L, keylist))
[[3, 0, 5, 2], [None, None, 1, 4], [7, 2, 9, 1], [1, None, 8, 3]]
Answered By: amisotcm
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.