Tsyras
Tsyras

Reputation: 9

Python Nested List Grouping

I have a nested list in this format:

finalValues = [ [x,123] , [x,23542] , [y,56] , [y,765] , [y,54] , [z,98] ]

I am writing to a text file like this currently (using a loop for the index):

outputFile.write("\n--------------------------------------------------")
outputFile.write("\nVariable: " + finalValues[index][0])
outputFile.write("\nNumber: " + finalValues[index][1])
outputFile.write("\n--------------------------------------------------")
outputFile.write("\n")

For this specific example that means I am printing out 6 unique outputs to the text file.

What is the easiest way to group the second value by the first value? So my output would be (EDIT --- I cannot format this perfectly like my output due to the forum formatting features, but you can get the general idea):

'--------------------------------------------------

Variable: x

Number: 123

Number: 23542

'--------------------------------------------------

'--------------------------------------------------

Variable: y

Number: 56

Number: 765

Number: 54

'--------------------------------------------------

'--------------------------------------------------

Variable: z

Number: 98

'--------------------------------------------------

Upvotes: 0

Views: 1447

Answers (4)

Whatang
Whatang

Reputation: 10356

One way to do it is to group the elements with itertools.groupby using operator.itemgetter to get the key value you're interested in. The list needs to be sorted by the key first.

import operator
import itertools
get_key = operator.itemgetter(0)
finalValues.sort(key = get_key)
for key, group in itertools.groupby(finalValues, get_key):
    outputFile.write("\n--------------------------------------------------")
    outputFile.write("\nVariable: " + key)
    for pair in group:
        outputFile.write("\nNumber: " + pair[1])
    outputFile.write("\n--------------------------------------------------")
outputFile.write("\n")

Upvotes: 2

Moshe
Moshe

Reputation: 9879

To take the best of both answers:

A defaultdict is a dictionary that initialized values are given a 'default' value (docs here).

import collections

finalValues = [ [x,123] , [x,23542] , [y,56] , [y,765] , [y,54] , [z,98] ]

# The dictionary will map each variable to a list of numbers
groupedValues = collections.defaultdict(list)
for variable, number in finalValues:
    groupedValues[variable].append(number)

# The next step is to print them out:
for variable, numbers in groupedValues.iteritems():
    outputFile.write("\n--------------------------------------------------")
    outputFile.write("\nVariable: %s" % variable)
    for number in numbers:
        outputFile.write("\nNumber: %s" % number)
    outputFile.write("\n--------------------------------------------------")
    outputFile.write("\n")

Upvotes: 1

dckrooney
dckrooney

Reputation: 3121

You could use a dictionary to handle this:

output_dict = {}
for elt in finalValues:
    output_dict[elt[0]] = output_dict.get(elt[0], []) + [elt[1]]

for key in output_dict.keys():
    outputFile.write("\n--------------------------------------------------")
    outputFile.write("\nVariable: " + key

    for elt in output_dict[key]:
        outputFile.write("\nNumber: " + elt)

    outputFile.write("\n--------------------------------------------------")
    outputFile.write("\n")

EDIT:

Looking at your question again, it's not clear what x, y, and z are.

If they're strings, then the dictionary approach should work fine. However, if they are some other object, then you need to make sure they are immutable (otherwise you can't use them as keys in the dictionary).

Upvotes: 0

Andrew Cox
Andrew Cox

Reputation: 10988

The easiest way of doing this is to create a list defaultdict and then iterate over the list using the first element of the child list as the key and append the second element to the default list.

Once you have the list just iterate over the keys (and then the list in it) to print your data.

import collections
finalValues = [ [x,123] , [x,23542] , [y,56] , [y,765] , [y,54] , [z,98] ]
d = collections.defaultdict(list)
for k in finalValues:
  d[k[0]].append(k[1])

d in this case will evalutate to

defaultdict(<type 'list'>, {'y': [56, 765, 54], 'x': [123, 23542], 'z': [98]})

Upvotes: 1

Related Questions