apak23
apak23

Reputation: 11

Sorting the alphanumeric values of a dictionary in python

I am trying to sort a dictionary in python which is like below: In this scenario my dictionary has 'ESPN' and 'AAA' are the keys and values are below

'ESPN': [
    'ESPN 90 TO 100_1050',
    'ESPN 60 TO 70_1150',
    'ESPN 80 TO 90_1250',
    'ESPN 90 TO 100_1750',
    'ESPN 90 TO 100_900'
    'ESPN 90 TO 100_1650',
    'ESPN 70 TO 80_1350',
    'ESPN 20 TO 30_1450'
]

'AAA': [
    'AAA 90 TO 100_1050',
    'AAA 60 TO 70_1150',
    'AAA 80 TO 90_1250',
    'AAA 90 TO 100_1750',
    'AAA 90 TO 100_1650',
    'AAA 70 TO 80_1350',
    'AAA 20 TO 30_1450'
]

I am trying to sort this dictionary in such a way that i want the number after the ESPN and AAA in ascending way and also the number after the underscore.

For example like below

'ESPN': [
    'ESPN 20 TO 30_1450',
    'ESPN 60 TO 70_1150',
    'ESPN 70 TO 80_1350',
    'ESPN 80 TO 90_1250',
    'ESPN 90 TO 100_900',
    'ESPN 90 TO 100_1650',
    'ESPN 90 TO 100_1750',
]

I am trying regex and sort but i am not able to get it. Would really appreciate if someone could help. I also tried various sorting techniques but i always end up sorting the keys and not the values. Also in most scenarios its not working as expected as when i am having a value as AAA 20 to 30_900 it is not coming in order before AAA 20 TO 30_1450 but after it.

TIA

Upvotes: 0

Views: 162

Answers (3)

hilberts_drinking_problem
hilberts_drinking_problem

Reputation: 11602

You can use re.findall to extract all contiguous sequences of digits, convert to integers and apply a lexicographic sort.

key = lambda s: tuple(map(int, re.findall('\d+', s)))
result = {k: sorted(v, key=key) for k, v in data.items()}

# Output

In [156]: result
Out[156]: 
{'AAA': ['AAA 20 TO 30_1450',
  'AAA 60 TO 70_1150',
  'AAA 70 TO 80_1350',
  'AAA 80 TO 90_1250',
  'AAA 90 TO 100_1050',
  'AAA 90 TO 100_1650',
  'AAA 90 TO 100_1750'],
 'ESPN': ['ESPN 20 TO 30_1450',
  'ESPN 60 TO 70_1150',
  'ESPN 70 TO 80_1350',
  'ESPN 80 TO 90_1250',
  'ESPN 90 TO 100_900',
  'ESPN 90 TO 100_1050',
  'ESPN 90 TO 100_1650',
  'ESPN 90 TO 100_1750']}

Upvotes: 0

jpp
jpp

Reputation: 164693

Here's one way using successive str.split calls. Mapping to integers ensures that 900 will come before 1000.

def sorter(x):
    _, var1, _, var2 = x.split()
    var2a, var2b = var2.split('_')
    return list(map(int, (var1, var2a, var2b)))

res = sorted(d['ESPN'], key=sorter)

['ESPN 20 TO 30_1450',
 'ESPN 60 TO 70_1150',
 'ESPN 70 TO 80_1350',
 'ESPN 80 TO 90_1250',
 'ESPN 90 TO 100_900',
 'ESPN 90 TO 100_1050',
 'ESPN 90 TO 100_1650',
 'ESPN 90 TO 100_1750']

Upvotes: 1

Bill
Bill

Reputation: 11613

d = {
    'ESPN': [
        'ESPN 90 TO 100_1050',
        'ESPN 60 TO 70_1150',
        'ESPN 80 TO 90_1250',
        'ESPN 90 TO 100_1750',
        'ESPN 90 TO 100_1650',
        'ESPN 70 TO 80_1350',
        'ESPN 20 TO 30_1450'
    ],
    'AAA': [
        'AAA 90 TO 100_1050',
        'AAA 60 TO 70_1150',
        'AAA 80 TO 90_1250',
        'AAA 90 TO 100_1750',
        'AAA 90 TO 100_1650',
        'AAA 70 TO 80_1350',
        'AAA 20 TO 30_1450'
    ]
}
[v.sort() for v in d.values()]

Result:

{'AAA': ['AAA 20 TO 30_1450',
  'AAA 60 TO 70_1150',
  'AAA 70 TO 80_1350',
  'AAA 80 TO 90_1250',
  'AAA 90 TO 100_1050',
  'AAA 90 TO 100_1650',
  'AAA 90 TO 100_1750'],
 'ESPN': ['ESPN 20 TO 30_1450',
  'ESPN 60 TO 70_1150',
  'ESPN 70 TO 80_1350',
  'ESPN 80 TO 90_1250',
  'ESPN 90 TO 100_1050',
  'ESPN 90 TO 100_1650',
  'ESPN 90 TO 100_1750']}

Upvotes: 0

Related Questions