0

Update: By referencing this previous post I made my ultimate goal is much clearer. Combing 2D list of tuples and then sorting them in Python

With the following line of code

result = list(zip(*sorted(zip(l1, l2, l3, files_good_list), section(l1), key = lambda x: float(x[0]))))

Where section is

 def section(s):
     return[int(_) for _ in s.split(".")]

and l1, l2, l3, files_good_list are list of strings.

My goal is to combine these four list and them sort then by l1. Where

l1 = ['1', '1.1', '1.2', '1.10', '2.1', '3.1', '1', '1.1', '1.2', '1.3', '1.4', '2', '2.1', '2.10', '3', '3.1', '3.2', '3.3', '3.4', '3.5', '3.6', '3.7', '3.8']

My code works if I use

result = list(zip(*sorted(zip(l1, l2, l3, files_good_list), key = lambda x: float(x[0]))))

but it does it sorts l1 as '1', '1.1', 1.10', '1.2' where I want l1 to sort as '1', '1.1', '1.2', '1.10'. This is why I am trying to use the function section to sort in the order I want.

I found section from an answer to this post which is similar How do I sort a list of section numbers in Python?

However, when I try to pass it in as an argument I get this error.

 Traceback (most recent call last):
  File "<ipython-input-422-bbd574034cbd>", line 1, in <module>
     runfile('C:/Users/justin.white/Documents/Work/Regex_try.py', wdir='C:/Users/justin.white/Documents/Work')
  File "C:\Users\justin.white\AppData\Local\Continuum\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 699, in runfile
     execfile(filename, namespace)

  File "C:\Users\justin.white\AppData\Local\Continuum\Anaconda3\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 88, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)
   File "C:/Users/justin.white/Documents/Work/Regex_try.py", line 84, in <module>
     result = list(zip(*sorted(zip(l1, l2, l3, files_good_list), section(l1), key = lambda x: float(x[0]))))
  File "C:/Users/justin.white/Documents/Work/Regex_try.py", line 82, in section
     return[int(_) for _ in s.split(".")]
 AttributeError: 'list' object has no attribute 'split'

But when I do

sorted(l1, key=section)

I do not get an error and it sorts it in the order I need. So my question is why can I not pass section into sorted when it is in a zip?

If you need any clarification let me know. Thanks

Community
  • 1
  • 1
Jstuff
  • 1,266
  • 2
  • 16
  • 27
  • You're sorting by the floating-point value of your key, and wondering why it places `1.1` and `1.10` together, and `1.10` before `1.2`? Seems to me like that's exactly what you should expect... – twalberg Jun 02 '16 at 18:21
  • I understand that it does that, but that is not how I want it to sort. This is the reason for the function section, to sort it 1.1, 1.2, 1.10 instead of 1.1, 1.10, 1.2. – Jstuff Jun 02 '16 at 18:24
  • But the function signature for `sorted` is either `sorted(iterable, cmp=None, key=None, reverse=False)` (Python 2.x) or `sorted(iterable, key=None, reverse=False)` (Python 3.x). I'm not sure how you expect your `section` function to even play - it's likely being ignored as a extraneous argument... – twalberg Jun 02 '16 at 18:30
  • Alright I didn't realize, is there a different way I can do it? I am new to python and I have exhausted my limited programming knowledge. – Jstuff Jun 02 '16 at 18:32
  • @shouldn't it be `key=section()`? – gaganso Jun 02 '16 at 18:38
  • @SilentMonk No, `key` can be passed a `function pointer` of sorts where it will cal `section` with each value and use the returned result to compare against – Chrispresso Jun 02 '16 at 18:44
  • "l1 is a list of strings" ... `section(l1)` ... `def section(s): ... s.split(...)` so you are passing a list to `section` and trying to call the `.split()` method on the list `l1` but lists don't have that method, what is unclear about the error? – Tadhg McDonald-Jensen Jun 02 '16 at 18:46

2 Answers2

2

section accepts a string containing integers separated by dots, but in your code, you're passing it a list. A correct way to use it would be something like:

result = list(zip(*sorted(zip(l1, l2, l3, files_good_list), key = lambda x: section(x[0]))))

But then again, I'm not really sure what you're trying to do with that code section.

One piece of advice would be to avoid such one-liners and break up the code into more readable chunks. This makes it really hard for people to understand what you're trying to do.

tmarice
  • 458
  • 4
  • 8
0

I'll give you a quick example of what you want. Pretty much you have two portions to a section (at least in this example). You have x.y where x can be any number and I'm going to assume that y can be 1-10. In this case you can make a custom comparison function that weights x by the max value of y.

This would be done like so:

l1 = ['1', '1.1', '1.2', '1.10', '2.1', '3.1', '1', '1.1', '1.2', '1.3', '1.4', '2', '2.1', '2.10', '3', '3.1', '3.2', '3.3', '3.4', '3.5', '3.6', '3.7', '3.8']
def section(s):
    # Set the inital values
    s1, s2 = 0, 0
    # If there is a `.` then we have a subsection
    if s.find('.') != -1:
        s1, s2 = s.split('.')
        s1, s2 = int(s1), int(s2)
    # Otherwise it's whatever value is there
    else:
        s1 = int(s)
    # Perform the actual weighting of the section and subsection
    return s1*10+s2

print(sorted(l1, key=section))
# Prints ['1',
 '1',
 '1.1',
 '1.1',
 '1.2',
 '1.2',
 '1.3',
 '1.4',
 '1.10',
 '2',
 '2.1',
 '2.1',
 '2.10',
 '3',
 '3.1',
 '3.1',
 '3.2',
 '3.3',
 '3.4',
 '3.5',
 '3.6',
 '3.7',
 '3.8']
Chrispresso
  • 3,660
  • 2
  • 19
  • 31