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
CodePudding user response:
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 fromdata
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
.
CodePudding user response:
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]]