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
Asked By: Shoaib Noorestani

||

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']]
Answered By: FRINTSO

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']]))
Answered By: depperm

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']]
Answered By: buran

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’]]

Answered By: match