0

I'm trying to sort a list in a more advanced list. The list which I am treating is in the following format:

  1. 001 Concrete

  2. 005 Wood, dark

  3. 001 021

  4. 002 Linoleum

  5. 031 Concrete, dark

  6. 003 012

  7. 005 051

  8. 005 331

  9. 024 Wood, light

I want to sort the list in an order where the indices 0-2 are sorted first as these are always numbers, and after that (indices from there 3:)letters are to be prioritized as these are the titles. It should sort the list like so:

  1. 001 Concrete

  2. 001 021

  3. 002 Linoleum

  4. 003 012

  5. 005 Wood, dark

  6. 005 051

  7. 005 331

  8. 024 Wood, light

  9. List item

  10. 031 Concrete, dark

So far I've tried to remove items at indices of titles, sorting, and replacing the items, but with no success.

Thanks for your time.

Ask
  • 27
  • 6
  • 1
    Possible duplicate of [How to sort a list of objects based on an attribute of the objects?](https://stackoverflow.com/questions/403421/how-to-sort-a-list-of-objects-based-on-an-attribute-of-the-objects) – TrebledJ Dec 03 '18 at 10:26
  • What is the original data? Strings or some objects represented by these strings? –  Dec 03 '18 at 12:00
  • Those are all strings. Not dictionaries. – Ask Dec 03 '18 at 12:05

2 Answers2

1

If you want to sort strings then you may do it with the code:

a = ["001 Concrete", "005 Wood, dark", "001 021", "002 Linoleum", "031 Concrete, dark", "003 012", "005 051", "005 331", "024 Wood, light"]

def key_first(string):
    return string.split()[0]

def key_second(string):
    # first - detect if we deal with words or numbers
    val = string.split()[1][0].isdigit()
    # if numbers - it is ok
    if val:
        return string.split()[1]
    # if words - they should go before numbers - let's add space
    else:
        return ' ' + string.split()[1]

# sort words and secondary numbers
result = sorted(a, key=key_second)
# sort primary numbers
result = sorted(result, key=key_first)

The code seems to provide the desired output on the sample data.

  • Maybe you recall; yesterday you answered another one of my questions (succesfully) and I'm trying to apply that script ( https://stackoverflow.com/questions/53538057/appending-specific-indices-from-zipped-lists ) to this one. To sum it up, I have three other lists connected to the list that you just sorted above. How would you apply that code to this one? Again, thank you. – Ask Dec 03 '18 at 13:56
  • @Ask `That` code is pretty straightforward. Create dictionary `data_in = {0: result, 1: list_1, 2: list_2, 3: list_3}` and process it to get dictionary `data_out` where all lists are modified together. Of course, details matter for both codes - should lists be sorted together? what form should the output have? what if 5 lists instead of 4? and so on. But the codes are rather simple and it is kinda easy to modify and combine them. If it is not then maybe you should learn and practice basics of Python. Or not. It is up to you of course. –  Dec 03 '18 at 14:19
  • Well, I want to sort the lists together. So the sorting mask just created in this script could be applied to the other three lists as well. Could that be done as you say? I am taking basic python courses next to these programs, but I am trying to just throw myself into them. – Ask Dec 03 '18 at 14:36
  • @Ask No sorting mask is created here. If you want to sort N lists together with Python then you may use so-called Decorate-Sort-Undecorate pattern `zip(*sorted(zip(list_1, list_2, ...), key=...))`. `key_function` should be modified in this case. For example `def key_first(element): return element[0].split()[0]`. Of course, you may also create sorting mask somehow. Not sure if it is easily possible with built-in Python means. –  Dec 03 '18 at 14:42
  • Hi again, Poolka. I solved it with your help and I'll write an additional comment with the code. Thank you again. – Ask Dec 03 '18 at 15:21
0

The following is the (slightly modified) answer provided by @Poolka with some additional zipping described and requested in the comments of his comment.

list0=IN[0]
list1=IN[1]
list2=IN[2]
list3=IN[3]

def key_first(string):
    return string[0].split()[0]

def key_second(string):
    if string[0].split()[1][0].isdigit():
        return string[0].split()[1]
    else:
        return " " + string[0].split()[1]


list0,list1,list2,list3 = zip(*sorted(zip(list0,list1,list2,list3),key=key_second))

list0,list1,list2,list3 = zip(*sorted(zip(list0,list1,list2,list3),key=key_first))

Here I've set the output to be:

OUT = [list,list1,list2,list3]
Ask
  • 27
  • 6
  • Seems like legit solution to the problem. It needs polishing in my opinion - you may use list of lists or dictionary of lists instead of 4 separate lists. Also you may face problems with `key_second` - depends on the data you gonna sort. Wish you luck on your journey in the world of programming with Python ))) –  Dec 03 '18 at 15:58
  • @Poolka - Thank you for your help. Guidance really does wonders when trying to code your first programs. – Ask Dec 05 '18 at 10:01
  • @Poolka Hey Poolka, As you predicted using a list of lists/dictionary is what i want to do with my script now. How would you do that? So far I've used: comb = {idx: (IN[0][idx]) for idx in range(len(IN[0]))}, and then I've replaced my 4 lists with comb, or *comb when inside the zipped/sorted functions. Can you help me out (again)? – Ask Jan 10 '19 at 11:57