简体   繁体   中英

Pythonic way to sort the records with multiple columns

Let's say we have a lot of records in a file in the following fashion.

10.10.10.10(tcp/443) : Some SSL Vulnerability : Medium : Patched

10.10.10.11(tcp/888) : Some RCE Vulnerability : High : Not Patched

These records have the 3rd column with values Critical, High, Medium, Low .

What's the best possible pythonic way to sort these records in this manner : 1. Critical, 2.High, 3.Medium 4. Low ?

Example using IntEnum for a list of dictionary.

from enum import IntEnum
class Vulnerability(IntEnum):
    CRITICAL = 1
    HIGH = 2
    MEDIUM = 3
    LOW = 4

records = []
records.append({'v': Vulnerability.MEDIUM})
records.append({'v': Vulnerability.HIGH})
records.append({'v': Vulnerability.CRITICAL})
records.append({'v': Vulnerability.LOW})

print(records)
# [{'v': <Vulnerability.MEDIUM: 3>}, {'v': <Vulnerability.HIGH: 2>}, {'v': <Vulnerability.CRITICAL: 1>}, {'v': <Vulnerability.LOW: 4>}]

print(records[0]['v'] < records[1]['v'])
# False

print(sorted(records, key = lambda k: k['v']))
# [{'v': <Vulnerability.CRITICAL: 1>}, {'v': <Vulnerability.HIGH: 2>}, {'v': <Vulnerability.MEDIUM: 3>}, {'v': <Vulnerability.LOW: 4>}]

If you can transform your table into a pandas data frame (for example, using pandas.read_csv ), then this will do the job:

import pandas as pd
df=pd.DataFrame({'a':[1,2,3,4,5,6],'b':['a','b','c','d','e','f'],'val':['critical','high','low','medium','critical','low']})
df['val'] = pd.Categorical(df['val'],['critical','high','medium','low'])
df.sort_values(by='val',inplace=True)

Then at the beginning df was

    a   b   val
0   1   a   critical
1   2   b   high
2   3   c   low
3   4   d   medium
4   5   e   critical
5   6   f   low

and in the end df is

    a   b   val
0   1   a   critical
4   5   e   critical
1   2   b   high
3   4   d   medium
2   3   c   low
5   6   f   low

In the code above, the line that specified the order was

df['val'] = pd.Categorical(df['val'],['critical','high','medium','low'])

Here's a pure Python solution, using a dictionary to convert the Critical, High, Medium, Low strings to their numeric values; that numeric value is used as the sorting key function argument to list.sort . My key function also uses the first field of each record as a secondary sorting key so that in each of the sections sorted by grade the entries are also sorted by that first field.

Since your question only includes 2 lines of sample data I've constructed some simple fake data.

data = '''\
00 : abc : Low
01 : def : High
02 : ghi : Low
03 : jkl : Medium
04 : mno : High
05 : pqr : Medium
06 : stu : High
07 : vwx : Medium
08 : yza : High
09 : bcd : High
10 : efg : High
11 : hij : Critical
12 : klm : Critical
13 : nop : Medium
14 : qrs : High
15 : tuv : Critical
'''.splitlines()
data = [row.split(' : ') for row in data]

grades = {'Critical': 1, 'High': 2, 'Medium': 3, 'Low': 4}

data.sort(key=lambda t: (grades[t[2]], t[0]))
for row in data:
    print(' : '.join(row))

output

11 : hij : Critical
12 : klm : Critical
15 : tuv : Critical
01 : def : High
04 : mno : High
06 : stu : High
08 : yza : High
09 : bcd : High
10 : efg : High
14 : qrs : High
03 : jkl : Medium
05 : pqr : Medium
07 : vwx : Medium
13 : nop : Medium
00 : abc : Low
02 : ghi : Low

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM