Matthew K.
Matthew K.

Reputation: 129

How do I group nested lists based on the first element?

I have a nested list containing strings which I want to group based on the first element of a nested list. After grouping them, I then want to remove any duplicate first elements and convert the list to a simple string seperated by a semicolon.

What I have managed so far is to output the simple string as well as removing duplicate first elements. I did this by saving the first element of the list in a new empty list, and using the if/else statement to decide what to append to the new output list.

exampleinput = ["[['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'], ['1','2','5'],['1','7','8']]"]

def makestring(n):
  str1 = ' '.join(n)
  return str1

def transform(n):
  first = []
  output = []
  for i in n:
    if i[0] not in first:
      output.append(makestring(i))
    else:
      string1 = makestring(i[1:])
      output.append(string1)
    first.append(i[0])
  return output

for i in exampleinput:
  print(transform(eval(i.strip())))

Example input:

[['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'],['1','2','5'],['1','7','8']] 

Desired output:

['1 2 3 ; 4 6 ; 2 5 ; 7 8', '2 1 2', ' 3 4 2']

Actual output:

['1 2 3', '4 6', '2 1 2', '3 4 2, '2 5', '7 8'] 

Any thoughts? Thanks in advance!

Upvotes: 1

Views: 1366

Answers (3)

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

With itertools.groupby function:

from itertools import groupby

inp_list = [['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'],['1','2','5'],['1','7','8']]
res = []
for k, g in groupby(sorted(inp_list, key=lambda x: x[0]), key=lambda x: x[0]):
    item1, *rest = g
    res.append('; '.join(map(' '.join, [item1] + [i[1:] for i in rest])) 
               if rest else ' '.join(item1))

print(res)

The output:

['1 2 3; 4 6; 2 5; 7 8', '2 1 2', '3 4 2']

Bonus solution with just using an auxiliary grouping dictionary:

inp_list = [['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'],['1','2','5'],['1','7','8']]
groups_dict = {}
for sub_l in inp_list:
    if sub_l[0] not in groups_dict:
        groups_dict[sub_l[0]] = ' '.join(sub_l)
    else:
        groups_dict[sub_l[0]] += '; ' + ' '.join(sub_l[1:])
res = list(groups_dict.values())

print(res)   # ['1 2 3; 4 6; 2 5; 7 8', '2 1 2', '3 4 2']

Upvotes: 2

Jack Adee
Jack Adee

Reputation: 73

Instead of appending to string one you are appending to the output in the order which given. Here is the code I got to work:

exampleinput = ["[['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'], ['1','2','5'],['1','7','8']]"]

def makestring(i):
    return "".join(i)

def main(i):
    string1 = ""
    first = ["1"] # for (123)
    output = []
    string1 += makestring(i[0])
    for x in i[1:]:
        if x[0] in first:
            string1 += " ; "+makestring(x[1:])
        else:
            output.append(makestring(x))
            first.append(x[0])
    return [string1] + output

if __name__ == "__main__":
    print(main(eval(exampleinput[0].strip())))

This returns the output: ['123 ; 46 ; 25 ; 78', '212', '342']

Upvotes: 0

Shahab Rahnama
Shahab Rahnama

Reputation: 1012

First I use the join method to create a list of strings

signal = [['1','2','3'],['1','4','6'],['2','1','2'],['3','4','2'],['1','2','5'],['1','7','8']]
my_list =[" ".join(x) for x in [y for y in signal] ]

then search list from end to start to the comparison the first character of that string is in other items if it's true and it's not same item and index of item greater than item that selected then removes it.

for i in range(len(my_list)-1,0,-1):
    for j in my_list:
        if my_list[i][0] == j[0] and my_list[i] != j and i > my_list.index(j):
            my_list[i]= my_list[i][1:]

print(my_list)

output:

['1 2 3', ' 4 6', '2 1 2', '3 4 2', ' 2 5', ' 7 8']

Upvotes: 0

Related Questions