I currently have code that, given a list, splits the names by the regexp in the selector (user defined) and sorts by the key (location - also user defined).
The key can be a list of keys in the order in which they should be sorted.
For example:
selector = r'.*(FF|TT|SS)_([-\.\d]+v)_([-\.\d]+c)_(FF|TT|SS).*'
key = [2,1,3]
Would sort by temp, voltage, secondary process.
That part of the code works perfectly. Now, I need help figuring out how to sort if given a custom {key:order} paired dictionary. For example:
{
0: ['FF', 'TT', 'SS'],
3: ['SS', 'TT', 'FF']
}
Basically, this would sort key 0 with FF TT SS order and then sort key 3 with SS TT FF.
Here's what I have so far:
import re
def sort_names(format_ids, selector, key=1, forced_order=None):
if isinstance(key, int):
key = [key]
def convert(x):
try:
return float(x[:-1])
except ValueError:
return x
def sort_keys(ik):
def split_fid(x):
x = re.findall(selector,x)[0]
return tuple([convert(x[i]) for i in ik])
return split_fid
if forced_order:
format_ids.sort(key=sort_keys(forced_order.keys()))
return list(format_ids)
else:
format_ids.sort(key=sort_keys(key))
return list(format_ids)
Need help with the forced_order section. Here's my input:
fids = ["synopsys_SS_2v_-40c_FF.lib",
"synopsys_SS_1v_-40c_TT.lib",
"synopsys_SS_1.2v_-40c_SS.lib",
"synopsys_SS_1.4v_-40c_SS.lib",
"synopsys_SS_2v_-40c_TT.lib",
"synopsys_FF_3v_25c_FF.lib",
"synopsys_TT_4v_125c_TT.lib",
"synopsys_TT_1v_85c_TT.lib",
"synopsys_TT_10v_85c_TT.lib",
"synopsys_FF_3v_-40c_SS.lib",
"synopsys_FF_3v_-40c_TT.lib"]
se = r'.*(FF|TT|SS)_([-\.\d]+v)_([-\.\d]+c)_(FF|TT|SS).*'
k = 3
fo = {
0: ['FF', 'TT', 'SS'],
3: ['SS', 'TT', 'FF']
}
retlist = sort_names(fids, se, k, fo)
Expected output for the forced_order part:
["synopsys_FF_3v_-40c_SS.lib",
"synopsys_FF_3v_-40c_TT.lib",
"synopsys_FF_3v_25c_FF.lib",
"synopsys_TT_4v_125c_TT.lib",
"synopsys_TT_1v_85c_TT.lib",
"synopsys_TT_10v_85c_TT.lib",
"synopsys_SS_1.2v_-40c_SS.lib",
"synopsys_SS_1.4v_-40c_SS.lib",
"synopsys_SS_1v_-40c_TT.lib",
"synopsys_SS_2v_-40c_TT.lib",
"synopsys_SS_2v_-40c_FF.lib"]
解决方案
I would call what you are trying to do here: Category Ordering. The dictionary you are passing in shows how to order certain fields. But what your dictionary does not, because it can not, show is how to order the fields. Python dicts are un-ordered on the keys. I would suggest keeping the meaning of the key field regardless of whether or not you pass in the dict which shows the category ordering.
Code:
As to how to make use of the information in the category_order, I think you need to change the convert() routine to something like:
def convert(i, x):
if i in category_order:
return category_order[i].index(x)
try:
return float(x[:-1])
except ValueError:
return x
Called like:
return tuple([convert(i, fields[i]) for i in key])
Full Routine:
def sort_names(format_ids, selector, key=1, category_order=None):
if isinstance(key, int):
key = [key]
if category_order is None:
category_order = {}
SELECTOR_RE = re.compile(selector)
def convert(i, x):
if i in category_order:
return category_order[i].index(x)
try:
return float(x[:-1])
except ValueError:
return x
def sort_keys():
def split_fid(fid):
fields = SELECTOR_RE.findall(fid)[0]
return tuple([convert(i, fields[i]) for i in key])
return split_fid
result = list(format_ids)
result.sort(key=sort_keys())
return result
Test Code:
fids = ["synopsys_SS_2v_-40c_FF.lib",
"synopsys_SS_1v_-40c_TT.lib",
"synopsys_SS_1.2v_-40c_SS.lib",
"synopsys_SS_1.4v_-40c_SS.lib",
"synopsys_SS_2v_-40c_TT.lib",
"synopsys_FF_3v_25c_FF.lib",
"synopsys_TT_4v_125c_TT.lib",
"synopsys_TT_1v_85c_TT.lib",
"synopsys_TT_10v_85c_TT.lib",
"synopsys_FF_3v_-40c_SS.lib",
"synopsys_FF_3v_-40c_TT.lib"]
se = r'.*(FF|TT|SS)_([-\.\d]+v)_([-\.\d]+c)_(FF|TT|SS).*'
k = [0, 3]
fo = {
0: ['FF', 'TT', 'SS'],
3: ['SS', 'TT', 'FF']
}
print('\n'.join(sort_names(fids, se, k, fo)))
Results:
synopsys_FF_3v_-40c_SS.lib
synopsys_FF_3v_-40c_TT.lib
synopsys_FF_3v_25c_FF.lib
synopsys_TT_4v_125c_TT.lib
synopsys_TT_1v_85c_TT.lib
synopsys_TT_10v_85c_TT.lib
synopsys_SS_1.2v_-40c_SS.lib
synopsys_SS_1.4v_-40c_SS.lib
synopsys_SS_1v_-40c_TT.lib
synopsys_SS_2v_-40c_TT.lib
synopsys_SS_2v_-40c_FF.lib
Alternate Sort Key Results:
print('\n'.join(sort_names(fids, se, [2, 1, 3], fo)))
Gives:
synopsys_SS_1v_-40c_TT.lib
synopsys_SS_1.2v_-40c_SS.lib
synopsys_SS_1.4v_-40c_SS.lib
synopsys_SS_2v_-40c_TT.lib
synopsys_SS_2v_-40c_FF.lib
synopsys_FF_3v_-40c_SS.lib
synopsys_FF_3v_-40c_TT.lib
synopsys_FF_3v_25c_FF.lib
synopsys_TT_1v_85c_TT.lib
synopsys_TT_10v_85c_TT.lib
synopsys_TT_4v_125c_TT.lib