How to Sort a List of Strings

How to sort a list of strings?

Basic answer:

mylist = ["b", "C", "A"]
mylist.sort()

This modifies your original list (i.e. sorts in-place). To get a sorted copy of the list, without changing the original, use the sorted() function:

for x in sorted(mylist):
print x

However, the examples above are a bit naive, because they don't take locale into account, and perform a case-sensitive sorting. You can take advantage of the optional parameter key to specify custom sorting order (the alternative, using cmp, is a deprecated solution, as it has to be evaluated multiple times - key is only computed once per element).

So, to sort according to the current locale, taking language-specific rules into account (cmp_to_key is a helper function from functools):

sorted(mylist, key=cmp_to_key(locale.strcoll))

And finally, if you need, you can specify a custom locale for sorting:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'),
key=cmp_to_key(locale.strcoll)) == [u'aa', u'Ab', u'ad']

Last note: you will see examples of case-insensitive sorting which use the lower() method - those are incorrect, because they work only for the ASCII subset of characters. Those two are wrong for any non-English data:

# this is incorrect!
mylist.sort(key=lambda x: x.lower())
# alternative notation, a bit faster, but still wrong
mylist.sort(key=str.lower)

How to sort a list, only sorting strings?

Picked up this cool trick from @JonClements the other day.

Here goes:

gen = iter(sorted([x for x in lst if isinstance(x, str)]))
new_lst = [next(gen) if isinstance(x, str) else x for x in lst]
print(new_lst)
# ['Foo', 1, 2, 'Hello', 6, 'World', 3]

Sort the strings separately and create a generator expression from the sorted strings. In a list comprehension, pick objects alternately from the gen. exp. using a ternary conditional if only the items in the original position is a string, otherwise, pick an item (an integer) from the initial list.

Sort a list of strings using a user-provided order in Python

You can use sorted(), and then generate the key parameter by using map() to map each letter to its priority (sorted() then uses tuple comparison to generate the ordering):

data = ['ayyaaauu', 'shhasyhh', 'shaash']
ordering = ['s', 'y', 'u', 'h', 'a']
priorities = {letter: index for index, letter in enumerate(ordering)}

result = sorted(data, key=lambda x: tuple(map(lambda y: priorities[y], x)))

# Prints ['shhasyhh', 'shaash', 'ayyaaauu']
print(result)

How to Sort a Nested List of strings

Solution by Maintaining your Structure

If you can't really create a class wrapping the data in your nested List (for whatever reason), you could use the collection stream and define the sorted operation's logic as follows:

List<List<String>> listRes = data.stream()
.sorted((x, y) -> {
int res = x.get(0).compareTo(y.get(0)); //Comparing by name
if (res != 0) return res;
res = Integer.valueOf(x.get(1)).compareTo(Integer.valueOf(y.get(1))); //Comparing by age (numeric value)
if (res != 0) return res;
return x.get(2).compareTo(y.get(2)); //Comapring by city
})
.collect(Collectors.toList());

Link to test the code above:

https://ideone.com/RhW1VI

Alternative Solution

However, as it has been pointed out in the comments, a better approach would be to create a custom class representing your data in the nested List. Perhaps a simple record if you're using Java 14 or later with a factory method to retrieve an instance of your class from a nested List.

Then, with a stream you could map each nested list to your custom class and sort it with a Comparator.

Here is a snippet of the implementation:

public static void main(String[] args) {
List<List<String>> data = /* ... your initialization ... */

List<MyClass> listSorted = data.stream()
.map(list -> MyClass.createMyClass(list))
.sorted(Comparator.comparing(MyClass::getName).thenComparing(MyClass::getAge).thenComparing(MyClass::getCity))
.collect(Collectors.toList());

System.out.println(listSorted);
}

Mapping record

record MyClass(String name, int age, String city, String code, String country) {

public static MyClass createMyClass(List<String> list) {
if (list == null || list.size() < 5) {
return null;
}

MyClass mc = new MyClass();
mc.name = list.get(0);
mc.age = Integer.valueOf(list.get(1));
mc.city = list.get(2);
mc.code = list.get(3);
mc.country = list.get(4);

return mc;
}
}

Here there is also a link with both implementations:

https://ideone.com/UK9trV

Python: how to sort a list of strings by substring relevance?

You can use difflib.SequenceMatcher, to achieve something very similar to your desired output:

>>> import difflib
>>> l = ["foo bar SOME baz TEXT bob", "SOME foo bar baz bob TEXT", "SOME foo TEXT", "foo bar SOME TEXT baz", "SOME TEXT"]
>>> sorted(l, key=lambda z: difflib.SequenceMatcher(None, z, "SOME TEXT").ratio(), reverse=True)
['SOME TEXT', 'SOME foo TEXT', 'foo bar SOME TEXT baz', 'foo bar SOME baz TEXT bob', 'SOME foo bar baz bob TEXT']

If you can't tell the only difference is that the position of the two elements "foo bar SOME TEXT baz" and "SOME foo TEXT" are swapped compared to your desired output.

Sort a list of strings in java in alphabetical order

You can create a custom Comparator using Comparator.comparing and Comparator.thenComparing.

List<String> sortedIds = ids.stream().sorted(
Comparator.comparing((String s) -> s.substring(0, s.indexOf('-')))
.thenComparingInt(s -> Integer.parseInt(s.substring(s.indexOf('-') + 1))))
.collect(Collectors.toList());


Related Topics



Leave a reply



Submit