2

I have the following doubly-nested list:

records = [[['Jack', 'male', 1],['Jack', 'male', 2],['Jack', 'male', 3]],[['Sally', 'female', 1],['Sally', 'female', 2],['Sally', 'female', 3]]]

I want to sort this list according to this list...

list_order = ['female', 'male']

...such that the result is this:

records 
[[['Sally', 'female', 1],['Sally', 'female', 2],['Sally', 'female', 3]],[['Jack', 'male', 1],['Jack', 'male', 2],['Jack', 'male', 3]]]
holastello
  • 593
  • 1
  • 7
  • 16
  • https://stackoverflow.com/questions/10695139/sort-a-list-of-tuples-by-2nd-item-integer-value This still applies to your lists – Gigaflop Aug 09 '18 at 19:12
  • @Gigaflop agreed the strategy is basically the same, however I have a list of lists, rather than a list of tuples – holastello Aug 09 '18 at 19:36
  • Tuples and lists can be addressed in the same manner, like `(3, 4)[0]` is 3, and `[3, 4][0]` is 3. – Gigaflop Aug 10 '18 at 19:24

2 Answers2

1

This may be a bit more complicated than what you are asking for. I am assuming:

  1. You cannot guarantee that each group will contain only items from one "list_order" category

  2. You want the final list to be doubly-nested, with all "list_order" categories grouped together

  3. There is no ordering aside from the one column that matches "list_order"
  4. Items should be in the EXACT order they are listed in "list_order"

So, you could use the following code:

records = [[['Jack', 'male', 1],['Jack', 'male', 2],['Jack', 'male', 3]],[['Sally', 'female', 1],['Sally', 'female', 2],['Sally', 'female', 3]]]
list_order = ['female', 'male']

# "flatten" list into singly-nested list
records = [leaf for branch in records for leaf in branch]

# sort the items in the list by list_order 
# sorted passes each item in the list to the lambda function
# record[1] is the position of "male"/"female"
records = sorted(records, key=lambda record: list_order.index(record[1]))

# group the list by list_order again, creating doubly-nested list
records = [ [record for record in records if record[1] == item ] for item in list_order ]

print records

Try it online (with debugging printouts)!

Triggernometry
  • 573
  • 2
  • 9
0

You can use sum:

records = [[['Jack', 'male', 1],['Jack', 'male', 2],['Jack', 'male', 3]],[['Sally', 'female', 1],['Sally', 'female', 2],['Sally', 'female', 3]]]
list_order = ['female', 'male']
new_records = sorted(records, key=lambda x:sum(list_order.index(i[1]) for i in x))

Output:

[[['Sally', 'female', 1], ['Sally', 'female', 2], ['Sally', 'female', 3]], [['Jack', 'male', 1], ['Jack', 'male', 2], ['Jack', 'male', 3]]]
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • thanks, this works. can you explain what `sum` is doing? – holastello Aug 09 '18 at 19:32
  • @holastello `sum` creates a "score" of the number of times `"female"` or `"male"` occurs in each sublist. That way a value reflected the frequency of the target values can be used to determine a potential sorting swap. – Ajax1234 Aug 09 '18 at 19:42