Home > Mobile >  Sorting nested dictionary
Sorting nested dictionary

Time:05-20

I have some data, which look like this:

tuplelist = [
    (datetime.date(2020, 4, 20), 4.23, 'EUR'),
    (datetime.date(2020, 4, 20), 3.76, 'USD'),
    (datetime.date(2020, 4, 20), 4.21, 'EUR'),
    (datetime.date(2020, 4, 20), 5.20, 'GPB'),
    (datetime.date(2020, 4, 20), 3.77, 'USD'),
    (datetime.date(2020, 4, 20), 4.27, 'EUR'),
    (datetime.date(2020, 4, 20), 3.79, 'USD'),
    (datetime.date(2020, 4, 20), 4.30, 'EUR'),
    (datetime.date(2020, 4, 20), 5.14, 'GPB'),
    (datetime.date(2020, 4, 20), 3.77, 'USD'),
    (datetime.date(2020, 4, 25), 4.23, 'EUR'),
    (datetime.date(2020, 4, 25), 3.76, 'USD'),
    (datetime.date(2020, 4, 25), 4.21, 'EUR'),
    (datetime.date(2020, 4, 25), 5.20, 'GPB'),
    (datetime.date(2020, 4, 25), 3.77, 'USD'),
    (datetime.date(2020, 4, 27), 4.27, 'EUR'),
    (datetime.date(2020, 4, 27), 3.79, 'USD'),
    (datetime.date(2020, 4, 27), 4.30, 'EUR'),
    (datetime.date(2020, 4, 27), 5.14, 'GPB'),
    (datetime.date(2020, 4, 28), 3.77, 'USD'),
    (datetime.date(2020, 4, 28), 4.23, 'EUR'),
    (datetime.date(2020, 5, 2), 3.76, 'USD'),
    (datetime.date(2020, 5, 2), 4.21, 'EUR'),
    (datetime.date(2020, 5, 2), 5.20, 'GPB'),
    (datetime.date(2020, 5, 2), 3.77, 'USD'),
    (datetime.date(2020, 5, 2), 4.27, 'EUR'),
    (datetime.date(2020, 5, 5), 3.79, 'USD'),
    (datetime.date(2020, 5, 5), 4.30, 'EUR'),
    (datetime.date(2020, 5, 5), 5.14, 'GPB'),
    (datetime.date(2020, 5, 5), 3.77, 'USD'),
    (datetime.date(2020, 4, 20), 4.23, 'EUR'),
    (datetime.date(2020, 4, 20), 3.76, 'USD'),
    (datetime.date(2020, 4, 20), 4.21, 'EUR'),
    (datetime.date(2020, 4, 20), 5.20, 'GPB'),
    (datetime.date(2020, 4, 20), 3.77, 'USD'),
    (datetime.date(2020, 4, 20), 4.27, 'EUR'),
    (datetime.date(2020, 4, 20), 3.79, 'USD'),
    (datetime.date(2020, 4, 20), 4.30, 'EUR'),
    (datetime.date(2020, 4, 20), 5.14, 'GPB'),
    (datetime.date(2020, 4, 20), 3.77, 'USD'),
    (datetime.date(2020, 4, 25), 4.23, 'EUR'),
    (datetime.date(2020, 4, 25), 3.76, 'USD'),
    (datetime.date(2020, 4, 25), 4.21, 'EUR'),
    (datetime.date(2020, 4, 25), 5.20, 'GPB'),
    (datetime.date(2020, 4, 25), 3.77, 'USD'),
    (datetime.date(2020, 4, 27), 4.27, 'EUR'),
    (datetime.date(2020, 4, 27), 3.79, 'USD'),
    (datetime.date(2020, 4, 27), 4.30, 'EUR'),
    (datetime.date(2020, 4, 27), 5.14, 'GPB'),
    (datetime.date(2020, 4, 28), 3.77, 'USD'),
    (datetime.date(2020, 4, 28), 4.23, 'EUR'),
    (datetime.date(2020, 5, 2), 3.76, 'USD'),
    (datetime.date(2020, 5, 2), 4.21, 'EUR'),
    (datetime.date(2020, 5, 2), 5.20, 'GPB'),
    (datetime.date(2020, 5, 2), 3.77, 'USD'),
    (datetime.date(2020, 5, 2), 4.27, 'EUR'),
    (datetime.date(2020, 5, 5), 3.79, 'USD'),
    (datetime.date(2020, 5, 5), 4.30, 'EUR'),
    (datetime.date(2020, 5, 5), 5.14, 'GPB'),
    (datetime.date(2020, 5, 5), 3.77, 'USD')
]

I managed to group it by date an currency and sum the values of each curriency. Now, I'd like to sort the currency values in descending manner. However I got some problems with two values (the same problem is during sorting in ascending way, but then this values are at the end): Output

Do you have any clue if my sorting loop is correct? Moreover, it is possible not to change the dictionary to list, while sorting?

Here is my code:

# grouping elements by date and currency
result = {}
for key, values in groupby(tuplelist, lambda x: x[0]):
    for _, v1, v2 in values:
        result.setdefault(key, {}).setdefault(v2, []).append(v1)

# summing value of each currency of each day
result2 = {}
for key, values in result.items():
    for k, val in values.items():
        total = sum(val)
        result2.setdefault(key, {}).setdefault(k, "%.2f" % total)

print("-----------------------BEFORE SORTING------------------------------------")
for items in result2.items():
    print(items)

# sorting the values of currencies in descending order
sorted_dict = {}
for key, values in result2.items():
    sorted_values = sorted(values.items(), key=lambda item: item[1], reverse=True)
    sorted_dict[key] = sorted_values

print("-----------------------SORTED VALUES------------------------------------")
for items in sorted_dict.items():
    print(items)

CodePudding user response:

# grouping elements by date and currency
result = {}
for key, values in groupby(tuplelist, lambda x: x[0]):
    for _, v1, v2 in values:
        result.setdefault(key, {}).setdefault(v2, []).append(v1)

# summing value of each currency of each day
result2 = {}
for key, values in result.items():
    for k, val in values.items():
        total = sum(val)
        result2.setdefault(key, {}).setdefault(k, round(total,2))

print("-----------------------BEFORE SORTING------------------------------------")
for items in result2.items():
    print(items)

# sorting the values of currencies in descending order
sorted_dict = {}
for key, values in result2.items():
    sorted_values = sorted(values.items(), key=lambda item: item[1], reverse=True)
    sorted_dict[key] = sorted_values

print("-----------------------SORTED VALUES------------------------------------")
for items in sorted_dict.items():
    print(items)

I make a change at result2 where i change <"%.2f" % total> to <round(total,2)> as by using <"%.2f" % total> will turn your value to string, therefore unable to sort as per your requirement.

CodePudding user response:

As Shlim mentioned in his answer, the sorting in your current output is correct if you were sorting by string values. In order to sort them by their numeric values you can make the adjustments Shlim suggests.

My suggestion is instead of having so many loops why not just make it one loop? For example:

result = {}
for key, values in groupby(tuplelist, lambda x: x[0]):
    for _, v1, v2 in values:
        if key in result and v2 in result[key]:
            result[key][v2]  = v1
        elif key not in result:
            result[key] = {v2: v1}
        else:
            result[key][v2] = v1
    sorted_values = sorted(
        result[key].items(), key=lambda item: item[1], reverse=True
    )
    rounded = map(lambda x: (x[0], round(x[1],2)), sorted_values)
    result[key].update(list(rounded))

To answer your other question, you cannot sort a dictionary directly with any of the builtin sorting functions. This is because they all rely on integer indexes which dictionaries do not have.

  • Related