I'm having problems with sorting a dictionary from a text file which contains both strings and numbers in ascending order. The output comes out partially correct, but not all the components in the dictionary comes out in the right order.
The dictionary I'm working with is assembled as follows:
a 103,5
b 407,7
c 394,98
d 20,7
e 3,78
So my code prints the dictionary partially right, but some values are still in the wrong order, for example:
e 3,78
d 20,7
c 394,98
a 103,5
b 407,7
Here, c
and a should switch places since the value beside a
is smaller then that of c
. here's some code:
a_dictionary = {}
file = open("example.txt")
for line in file:
value, key = line.split()
a_dictionary[value] = key
sort_file = sorted(a_dictionary.items(), key=lambda x: x[1])
for i in sort_file:
print(i[0], i[1])
CodePudding user response:
You should not rely on a dictionary being in any particular order. Python (now) does make certain guarantees, but this is not good practice. In this case, you don't really need a dictionary. Why not just make a list of tuples?
Also, you are keeping your data in strings. Numeric data does not sort well when stored as strings. "100" is less than "2", which many people find disturbing.
mydata = []
file = open("example.txt")
for line in file:
data = line.rstrip().split()
mydata.append( (data[0], float(data[1])) )
mysort = sorted(mydata, key=lambda x: x[1])
for i in mysort:
print(i[0], i[1])
CodePudding user response:
Your dictionary's value type is str
, which means that '103,5'
is being treated as a string, not a number. I'm not sure how you got the order you gave, but when I run your code, I get the following order:
a 103,5
d 20,7
e 3,78
c 394,98
b 407,7
The second value is being compared alphabetically. Because "1" comes before "2", "103,5" is the first value. Just like "apple" comes before "bus". So you can see that it goes in order, 1, 2, 3, 39, 4.
To fix this, you need to convert your dictionary value into a float
. But because your input is using commas instead of decimals, you can't just use float(value)
. If this is because you are in a country where this is the norm, you should use locale.atof
instead of float
. After this, if you still need the output to use commas instead of decimal places, you'll need to format the output with locale.str
.
import locale
a_dictionary = {}
file = open("example.txt")
for line in file:
key, value = line.split()
value = locale.atof(value)
a_dictionary[key] = value
sort_file = sorted(a_dictionary.items(), key=lambda x: x[1])
for i in sort_file:
print(i[0], locale.str(i[1]))
If my assumption is wrong and you don't have the comma for locale reasons, then you can use the string replace
function to replace the comma with a decimal point.
I also swapped key
and value
, you have those backwards. Dictionaries are indexed by the key.
As Tim Roberts pointed out, you don't really seem to need a dictionary here. Unless there's more to the problem than we understand from your post.
CodePudding user response:
The problem is you're sorting the the two numbers in each dictionary value as a single string so they are compare alphabetically, not numerically. That can be corrected by splitting the the string up into two numbers and then convert them into a pair of integer values (and using that as the sort key).
with open("example.txt") as file:
a_dictionary = dict(line.split() for line in file)
sort_file = sorted(a_dictionary.items(), key=lambda p: tuple(map(int, p[1].split(','))))
for i in sort_file:
print(i[0], i[1])
Output:
e 3,78
d 20,7
a 103,5
c 394,98
b 407,7