Python convert repeating lists into sublists
Question:
I have multiple lists containing, e.g.
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
b = [['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]
I’d like to transform the data into sub-lists, for example like below:
OUTPUT:
a = [['server_1', 'abc', 'def'], ['server_2', 'abc']]
b = [['server_3', 'abc', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc', 'def'], ['server_6', 'abc']]
What I want to do is single out the server names and add any sub-data that is attached with that list into a single element like shown above.
Any help is appreciated
I tried using multiple loops and if statements to compare the previous value in the list to the next one, but to no avail.
An attempt below:
for part in repeating_list:
if part not in repeating_list:
new_list.append([part])
else:
pass (this should return it to sublist)
return new_list
Answers:
A simple solution to your problem uses a two-pass approach. This means that we start with grabbing the names of the servers first. And in the second pass we can use the server to extract the data.
Here is the code that exemplifies this:
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
b = [['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]
def solution(inp):
servers: list[str] = []
for x in inp:
if x[0] not in servers: servers.append(x[0])
output = []
for server in servers:
current_server_params = [server]
for x in inp:
if x[0] == server:
current_server_params.extend(x[1:])
output.append(current_server_params)
print(output)
solution(a)
solution(b)
solution(c)
Output:
[['server_1', 'abc', 'def'], ['server_2', 'abc']]
[['server_3', 'abc', 'def'], ['server_4', 'abc']]
[['server_5', 'abc', 'def'], ['server_6', 'abc']]
I would add a keys list (new_list_keys
) which can track index and can easily be checked if the key (part[0]
) is already there. If it’s not add part to new_list
and the relevant key to keys list. If it is, concat rest of the list to the list at idx of the key
def solution(repeating_list):
new_list = []
new_list_keys = []
for part in repeating_list:
if part[0] not in new_list_keys:
new_list.append(part)
new_list_keys.append(part[0])
else:
idx = new_list_keys.index(part[0])
new_list[idx]+=part[1:]
return new_list
print(solution([['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]))
print(solution([['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]))
print(solution([['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]))
You can use collections.defaultdict
to combine the sub-lists in one pass
from collections import defaultdict
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
def combine(my_list):
result = defaultdict(list)
for key, value in my_list:
result[key].append(value)
return [[key] + value for key, value in result.items()]
print(combine(a))
output
[['server_1', 'abc', 'def'], ['server_2', 'abc']]
A simple approach is to use a dict
, storing the first element as the key, then appending the 2nd element to the value as a list.
from collections import defaultdict
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
# Use a defaultdict to avoid testing for key in dict
data = defaultdict(list)
for item in a:
data[item[0]].append(item[1])
# Convert to a list of lists, flattening the values
print([[k, *v] for k, v in data.items()])
[[‘server_1’, ‘abc’, ‘def’], [‘server_2’, ‘abc’]]
I have multiple lists containing, e.g.
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
b = [['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]
I’d like to transform the data into sub-lists, for example like below:
OUTPUT:
a = [['server_1', 'abc', 'def'], ['server_2', 'abc']]
b = [['server_3', 'abc', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc', 'def'], ['server_6', 'abc']]
What I want to do is single out the server names and add any sub-data that is attached with that list into a single element like shown above.
Any help is appreciated
I tried using multiple loops and if statements to compare the previous value in the list to the next one, but to no avail.
An attempt below:
for part in repeating_list:
if part not in repeating_list:
new_list.append([part])
else:
pass (this should return it to sublist)
return new_list
A simple solution to your problem uses a two-pass approach. This means that we start with grabbing the names of the servers first. And in the second pass we can use the server to extract the data.
Here is the code that exemplifies this:
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
b = [['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]
c = [['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]
def solution(inp):
servers: list[str] = []
for x in inp:
if x[0] not in servers: servers.append(x[0])
output = []
for server in servers:
current_server_params = [server]
for x in inp:
if x[0] == server:
current_server_params.extend(x[1:])
output.append(current_server_params)
print(output)
solution(a)
solution(b)
solution(c)
Output:
[['server_1', 'abc', 'def'], ['server_2', 'abc']]
[['server_3', 'abc', 'def'], ['server_4', 'abc']]
[['server_5', 'abc', 'def'], ['server_6', 'abc']]
I would add a keys list (new_list_keys
) which can track index and can easily be checked if the key (part[0]
) is already there. If it’s not add part to new_list
and the relevant key to keys list. If it is, concat rest of the list to the list at idx of the key
def solution(repeating_list):
new_list = []
new_list_keys = []
for part in repeating_list:
if part[0] not in new_list_keys:
new_list.append(part)
new_list_keys.append(part[0])
else:
idx = new_list_keys.index(part[0])
new_list[idx]+=part[1:]
return new_list
print(solution([['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]))
print(solution([['server_3', 'abc'], ['server_3', 'def'], ['server_4', 'abc']]))
print(solution([['server_5', 'abc'], ['server_6', 'abc'], ['server_5', 'def']]))
You can use collections.defaultdict
to combine the sub-lists in one pass
from collections import defaultdict
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
def combine(my_list):
result = defaultdict(list)
for key, value in my_list:
result[key].append(value)
return [[key] + value for key, value in result.items()]
print(combine(a))
output
[['server_1', 'abc', 'def'], ['server_2', 'abc']]
A simple approach is to use a dict
, storing the first element as the key, then appending the 2nd element to the value as a list.
from collections import defaultdict
a = [['server_1', 'abc'], ['server_2', 'abc'], ['server_1', 'def']]
# Use a defaultdict to avoid testing for key in dict
data = defaultdict(list)
for item in a:
data[item[0]].append(item[1])
# Convert to a list of lists, flattening the values
print([[k, *v] for k, v in data.items()])
[[‘server_1’, ‘abc’, ‘def’], [‘server_2’, ‘abc’]]