I have a list containing thousands of sub-lists. Each of these sub-lists contain a combination of mixed strings and boolean values, for example:
lst1 = [['k', 'b', False], ['k', 'a', True], ['a', 'a', 'a'], ['a', 'b', 'a'], ['a', 'a' , False], ...]
I want to sort this list in accordance with the contents of the sub-lists, like:
lst2 = [['a', 'a', 'a'], ['a', 'a' , False], ['a', 'b', 'a'], ['k', 'a', True], ['k', 'b', False], ...]
I've tried sorting it like this:
lst2 = sorted([list(sorted(x)) for x in lst1])
print(lst2)
This doesn't work because of the combination of boolean values with strings in some fields, so I get TypeError: '<' not supported between instances of 'bool' and 'str'
.
I've also tried a brute force method, creating every possible combination and then checking them to see if which are in the first list:
col1 = ['a', 'b', 'c', d, e, f, g, h, i, j, k, ..., True, False]
col2 = ['a', 'b', 'c', d, e, f, g, h, i, j, k, ..., True, False]
col3 = ['a', 'b', 'c', d, e, f, g, h, i, j, k, ..., True, False]
lst2 = list()
for t1 in col1:
for t2 in col2:
for t3 in col3:
test_sublist = [t1, t2, t3]
if test_sublist in lst1:
lst2.append(test_sublist)
This way works well enough, because I'm able to automatically create sorted lists for each column, col 1
, col 2
, and col 3
, but it takes way too long to run (more than 3 days).
Is there a better solution for sorting mixed string/boolean lists like these?
These handle any lengths, not just length 3. And bools in any places, not just the last column. For keying, they turn each element of each sublist into a tuple.
Solution 1:
sorted(lst1, key=lambda s: [(e is False, e is True, e) for e in s])
Turns strings into (False, False, thestring)
so they come first.
Turns True
into (False, True, True)
so it comes next.
Turns False
into (True, False, False)
so it comes last.
Though I think of it the reverse way, as in "First deprioritize False
, then deprioritize True
". The general form is key=lambda x: (shall_come_last(x), x)
.
Solution 2:
sorted(lst1, key=lambda s: [((e is True) + 2 * (e is False), e) for e in s])
Turns strings into (0, thestring)
so they come first.
Turns True
into (1, True)
so it comes next.
Turns False
into (2, False)
so it comes last.
Solution 3:
sorted(lst1, key=lambda s: [(0, e) if isinstance(e, str) else (2 - e,) for e in s])
Turns strings into (0, thestring)
so they come first.
Turns True
into (1,)
so it comes next.
Turns False
into (2,)
so it comes last.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With