1

I have a dictionary with an array as elements. Say:

masterListShort = {'a': [5, 2, 1, 2], 'b': [7, 2, 4, 1], 'c': [2, 0, 1, 1]}

I would like to reverse sort this dictionary by the first element of the values. I would then like to write my output to a tab delimited file like this:

<key>    <value1>    <value2>    <value3>    etc.

My current code where I write my dictionary to file looks like this:

# write the masterListShort to file
outFile2 = open('../masterListShort.tsv', 'w')
for item in sorted(masterListShort):
    tempStr = '\t'.join(map(str, masterListShort[item]))
    outFile2.write(str(item) + '\t' + tempStr + '\n')

outFile2.close()

This code works fine, it just does not sort the list. I want my output to be written in a tab delimited file format. So:

b    7    2    4    1
c    5    2    1    2
a    2    0    1    1

I have found the following commands so far, and was wondering if i could apply them to my code:

import operator
sorted(myDict, key=operator.itemgetter(1))
2
  • 1
    Please do test your samples; your sample dictionary is using entirely incorrect syntax. Commented May 7, 2014 at 10:52
  • Sorry, i just wrote it from head. Commented May 7, 2014 at 10:56

2 Answers 2

8

You'll need to sort the values then, on the first index (so 0 for zero-based indexing), and tell sorted() to reverse the order:

import operator

sorted(myDict.values(), key=operator.itemgetter(0), reverse=True)

Without the dict.values() call you are trying to sort the keys instead.

Demo:

>>> import operator
>>> myDict = {'a': [5, 2, 1, 2], 'b': [7, 2, 4, 1], 'c': [2, 0, 1, 1]}
>>> sorted(myDict.values(), key=operator.itemgetter(0), reverse=True)
[[7, 2, 4, 1], [5, 2, 1, 2], [2, 0, 1, 1]]

If you wanted to output key-value pairs, then use dict.items() and use lambda to access the first index on just the value:

sorted(myDict.items(), key=lambda i: i[1][0], reverse=True)

Demo:

>>> sorted(myDict.items(), key=lambda i: i[1][0], reverse=True)
[('b', [7, 2, 4, 1]), ('a', [5, 2, 1, 2]), ('c', [2, 0, 1, 1])]

In both cases, there is actually not that much point on sorting just by the first element; you can just leave the lists to sort naturally:

sorted(myDict.values(), reverse=True)  # sort just the values
sorted(myDict.items(), key=operator.itemgetter(1), reverse=True)  # sort items

as a list of lists is sorted in lexicographical ordering; if the first elements are equal, then two lists are ordered based on the second element, etc.

To write this out to a tab-delimited file, use the csv module; it'll take care of converting values to strings, writing the tab delimiters and handle newlines:

import csv

with open('../masterListShort.tsv', 'wb') as outfh:
    writer = csv.writer(outfh, delimiter='\t')
    for key, values in sorted(myDict.items(), key=operator.itemgetter(1), reverse=True):
        writer.writerow([key] + values)
Sign up to request clarification or add additional context in comments.

4 Comments

Yes, I had this. the problem I have here is that I cannot get the original key anymore. (I would like to write my output as key + value)
@MrFronk: Then why did you not ask for that instead? Your sample output showed just the values.
I reformulated my question, I hope the quetion is clear now. Sorry for inconvenience caused
@MrFronk: I've added a section on writing the TSV file for you too now; it'll write key value0 value1 ... valueN per row, with the rows sorted on value0.
0

You can sort the list of tuples that dict.items() gives;

myDict = {'a': [5, 2, 1, 2], 'b': [7, 2, 4, 1], 'c': [2, 0, 1, 1]}

print myDict.items()
#[('a', [5, 2, 1, 2]), ('c', [2, 0, 1, 1]), ('b', [7, 2, 4, 1])]

print sorted(myDict.items(), key=lambda x: x[1][0], reverse=True))
#[('c', [2, 0, 1, 1]), ('a', [5, 2, 1, 2]), ('b', [7, 2, 4, 1])]

the key keyword argument of sorted is a function you provide it with, which returns something the function can use to sort each element of the list you give it to be sorted on.

lambda x: x[1][0] is just a quick way of making a function which you could have used instead;

i.e.

print sorted(myDict.items(), key=lambda x: x[1][0])

is the same as

def sortFunction(x):
  return x[1][0]

print sorted(myDict.items(), key=sortFunction)

The reason it's giving x[1][0] is because the list myDict.items() is a 2D list; each element is a tuple, where the first element is the key, and the second element is the value. so x[1] is the value (i.e. the lists assigned to each key). And you want to sort on their first values, so we sort on x[1][0].

Now it's just a case of printing them in the format you want;

for key, value in sorted(myDict.items(), key=sortFunction, reverse=True):
  print key + "\t" + "\t".join([str(v) for v in value])

That will give:

b   7   2   4   1
a   5   2   1   2
c   2   0   1   1

1 Comment

I reformulated my question, I hope the quetion is clear now. Sorry for inconvenience caused

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.