1

Just starting to work on python and having difficulties sorting string list by multiple/varying number of matches. Basically, given a list of strings, I need to split each string by a given regex (user provided) then sort by given list of keys (locations). The key can either be single integer or a list in the order in which they should be sorted. For example:

regex = r'.(FF|TT|SS)_([-.\d]+v)_([-.\d]+c)_(FF|TT|SS).'

key = [2,1,3]

Would sort the list of strings by location2, location1, location3.

I have the following that works for a fixed number of locations/keys, but can't figure out how to get it to work of varying number of 'keys':

import re

strlist = ["synopsys_SS_2v_-40c_SS.lib","synopsys_SS_1v_-40c_SS.lib","synopsys_SS_2v_-40c_TT.lib","synopsys_FF_3v_-40c_FF.lib", "synopsys_TT_4v_125c_TT.lib", "synopsys_TT_1v_-40c_TT.lib"]
regex = r'.*(FF|TT|SS)_([-\.\d]+v)_([-\.\d]+c)_(FF|TT|SS).*'
key = [2,1,3]

sfids_single = sorted(strlist, key=lambda name: ( 
  re.findall(regex,name)[0][key[0]], 
  re.findall(regex,name)[0][key[1]],
  re.findall(regex,name)[0][key[2]]))

Tried the following but it does not seem to work:

fids_single = sorted(strlist, key=lambda name: (re.findall(regex,name)[0][i] for i in key))

Also tried (w/o success):

for i in key:
  strlist.sort(key=lambda name: re.findall(regex,name)[0][key[i]])

Expected result:

['synopsys_SS_1v_-40c_SS.lib', 'synopsys_TT_1v_-40c_TT.lib', 'synopsys_SS_2v_-40c_SS.lib', 'synopsys_SS_2v_-40c_TT.lib', 'synopsys_FF_3v_-40c_FF.lib', 'synopsys_TT_4v_125c_TT.lib']

Am I on the wrong track completely? Any guidance is greatly appreciated.

8
  • Are you having trouble splitting the strings or sorting the resultant list? Commented Jun 28, 2017 at 18:55
  • And can you show a sample of the desired output? Commented Jun 28, 2017 at 19:01
  • Is this a homework question? Commented Jun 28, 2017 at 19:02
  • I'm not having trouble splitting, just sorting by a given set of keys. This is not a homework question, it's part of code I'm writing for work. Commented Jun 28, 2017 at 20:38
  • Added expected results Commented Jun 28, 2017 at 20:52

2 Answers 2

2

Write a key function that will return the relevent portions of each string, in order of precedence, and use that function for the sort key.

one = ["synopsys_SS_2v_-40c_SS.lib","synopsys_SS_1v_-40c_SS.lib",
       "synopsys_SS_2v_-40c_TT.lib","synopsys_FF_3v_-40c_FF.lib",
       "synopsys_TT_4v_125c_TT.lib", "synopsys_TT_1v_-40c_TT.lib"]    

expected = ['synopsys_SS_1v_-40c_SS.lib', 'synopsys_TT_1v_-40c_TT.lib',
            'synopsys_SS_2v_-40c_SS.lib', 'synopsys_SS_2v_-40c_TT.lib',
            'synopsys_FF_3v_-40c_FF.lib', 'synopsys_TT_4v_125c_TT.lib']

Using your regular expression to split the string;

import operator, re
pattern = r'.*(FF|TT|SS)_([-\.\d]+v)_([-\.\d]+c)_(FF|TT|SS).*'
rx = re.compile(pattern)
seq = [2,1,3]
def key(item, seq = seq):
    seq = operator.itemgetter(*seq)
    a, b, c, d = rx.findall(item)
    return seq([a, b, c, d])


one.sort(key = key)
assert one == expected

The key function can be written without using a regular expression which may make it a bit less complicated.

def key(item, seq = seq):
    seq = operator.itemgetter(*seq)
    _, a, b, c, d = item.split('_')
    d, _ = d.split('.')
    print a, b, c, d
    return seq([a, b, c, d])

You may want to use names that are more descriptive than a, b, c, d. It relies on the strings having the same pattern.

Sign up to request clarification or add additional context in comments.

1 Comment

@Kidneys Your first attempt with for i in key was almost right, however the expression you used returns a generator. For a sorting key you want to use a tuple instead. So by using lambda name: tuple(... for i in key) it should work.
1

Many thanks to @a_guest for providing the missing piece of the puzzle. Here's the working solution:

fids_single = sorted(strlist, key=lambda name: tuple(re.findall(regex,name)[0][i] for i in key))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.