How to Sort a List of Objects Based on an Attribute of the Objects

How to sort a list of objects based on an attribute of the objects?

# To sort the list in place...
ut.sort(key=lambda x: x.count, reverse=True)

# To return a new list, use the sorted() built-in function...
newlist = sorted(ut, key=lambda x: x.count, reverse=True)

More on sorting by keys.

Python, how to sort list of object?

The idea is still the same. Just that you will be looking for a specific attribute in the class object.

For your card class, you could do something like this:

hand = [ Card(10, 'H'), Card(2,'h'), Card(12,'h'), Card(13, 'h'), Card(14, 'h') ]

Then you could do

sorted_cards = sorted(hand, key=lambda x: x.rank)

The output looks something like this:

>>> [card.number for card in sorted_cards]
[2, 10, 12, 13, 14]

Sort list of objects by a specific attribute of these objects?

You're almost there. You just need to change your key a bit to use a lambda:

sorted(Student.all_students, key=lambda x: -len(x.name))

This'll sort your student list in descending order of name length (notice the -len(...).

If you wanted to use attrgetter, you'd need to change your key to key=lambda x: -len(operator.attrgetter('name')(x)). But at that point, it becomes simpler to just use x.name.


Here's a demonstration. I've added a __repr__ method so it becomes clearer.

In [320]: def __repr__(self): return 'Student(%s %s)' %(self.name, self.surname)

In [321]: Student.__repr__ = __repr__

In [322]: sorted(Student.all_students, key=lambda x: -len(x.name))
Out[322]: [Student(Marcooooooo sss), Student(Jacobbbb anything), Student(Mat anything1)]

Faster way to sort a list of objects based on a attribute in Python

I believe the sort method is implemented using Timsort algorithm, so there is not much you can improve in terms of sorting.

What you can do is to insert the elements differently provided you have the control over the inserting part of code.

For example you could use a binary heap to optimize retreiving of the largest element (see heapq module in Python) or binary search tree to maintain the sorting order.
The data strcuture you choose, mainly depends on what do you want to do with the elements.

Python: Sort a list of objects based on their attributes

sorted, list.sort accept optional key parameter. Pass a key function. The return value of the function is used for comparison instead of the original value:

>>> from collections import namedtuple
>>> hero = namedtuple('hero', ['name', 'classes', 'level'])
>>>
>>> mainList = [
... hero(name='SirGoose', classes='Fighter', level=150 ),
... hero(name='Conan', classes='Barbarian', level=160 ),
... hero( name='KingArthur', classes='Knight', level=170 )
... ]
>>> sorted(mainList, key=lambda h: (h.name, h.level))
[hero(name='Conan', classes='Barbarian', level=160),
hero(name='KingArthur', classes='Knight', level=170),
hero(name='SirGoose', classes='Fighter', level=150)]

NOTE: the key function used here (lambda) returns a tuple. tuples are compared item by item. If the first items are same, the next items are compared, ...

>>> ('SirGoose', 12) < ('Barbarian', 160)
False
>>> ('SirGoose', 12) < ('SirGoose', 160)
True

Alternative using operator.attrgetter:

>>> import operator
>>> sorted(mainList, key=operator.attrgetter('name', 'level'))
[hero(name='Conan', classes='Barbarian', level=160),
hero(name='KingArthur', classes='Knight', level=170),
hero(name='SirGoose', classes='Fighter', level=150)]

java sort list of objects by specifiable attribute

It would be much simpler to use custom comparators:

To sort by name:

Arrays.sort(carArray, Comparator.comparing(Car::name));

To sort by colour:

Arrays.sort(carArray, Comparator.comparing(Car::colour));

So you could modify getSortedArray():

public static Car[] getSortedArray(Car[] carArray, Comparator<Car> comparator) {
Car[] sorted = carArray.clone()
Arrays.sort(sorted, comparator);
return sorted;
}

And call it like this:

Car[] sorted = getSortedArray(carArray, Comparator.comparing(Car::name));

Edit:

If you use a language version that does not support these features, you can create the comparators by explicitly creating a nested class that implements the Comparator interface.

This, for example, is a singleton Comparator that compares Car instances by name:

static enum ByName implements Comparator<Car> {
INSTANCE;

@Override
public int compare(Car c1, Car c2) {
return c1.name().compareTo(c2.name());
}
}

Then call:

Car[] sorted = getSortedArray(carArray, ByName.INSTANCE);

Java - sort list of objects based on object's value

It kind of depends on the data structure you have chosen. For example using arrays might be a bit harder to implement using the Comparator pattern. But if you have list of lists you can do it like that:

public class ComparatorClass implements Comparator<List<String>>{

private int compare(String s1, String s2) {
boolean b1 = s1.matches(".*[^0-9.\\-].*");
boolean b2 = s2.matches(".*[^0-9.\\-].*");

// if both are gonna find doubles
if (!b1 && !b2) {
Double d1 = Double.parseDouble(s1);
Double d2 = Double.parseDouble(s2);

return d1.compareTo(d2);
}
// if both are text, then compare as strings
else if (b1 && b2) {
return s1.compareTo(s2);
}
// otherwise return one or the other, depending on which is text/number
else return b2 ? -1 : 1;
}


@Override
public int compare(List<String> o1, List<String> o2) {
for(int i=0;i<Math.min(o1.size(), o2.size()); i++) {
int comparedAtThisLevel=compare(o1.get(i),o2.get(i));
if(comparedAtThisLevel!=0)
return comparedAtThisLevel;
}
return Integer.compare(o1.size(),o2.size());
}
}

This is a comparator for list of strings (and not just for two strings). I used your method to compare the two strings on the same level but then I iterate through the list of values and compare 1st with 1st, 2nd with 2nd, 3rd with 3rd etc. If all values match (or one of the lists ends) we compare the sizes and take the longer one

Then you can test it with that:

public static void main(String[] args) {
System.out.println(new Date()+": Let's start our StackOverflow helper project!");

List<List<String>> listOfLists=new ArrayList<>();



listOfLists.add(Arrays.asList("-22","123456","4234","5435345"));
listOfLists.add(Arrays.asList("-22","-3","-4"));
listOfLists.add(Arrays.asList("-22","11","Pillow"));

Collections.sort(listOfLists, new ComparatorClass());

}

Sorting (or partially sorting) a list of objects based on a specific attribute

Tuple is what you needed. Instead of storing scores in a heap, stores a tuple of (score, object) in the heap. It will try to compare by the score and return a list of tuples which you can use to retrieve the original objects. This will save you extra steps to retrieve objects by their scores:

heapq.nlargest(3, ((obj.score, obj) for obj in randomObjects))
# [(0.9996643881256989, <__main__.Object object at 0x155f730>), (0.9991398955041872, <__main__.Object object at 0x119e928>), (0.9858047551444177, <__main__.Object object at 0x15e38c0>)]

For a real world example: https://akuiper.com/console/g6YuNa_1WClp

Or as @shriakhilc commented, use key parameter in heapq.nlargest to specify you want to compare by score:

heapq.nlargest(3, randomObjects, lambda o: o.score)

Sorting a list of objects based on a nullable ArrayList attribute of that object using java 8

The problem you are facing is that Comparator.nullsLast would be used if you had null Patient objects. This is not your case, because you have null visits.

You should use it this way:

list.stream()
.sorted(Comparator.comparing(
s -> s.getVisits() == null || s.getVisits().isEmpty() ?
null :
s.getVisits().get(0),
Comparator.nullsLast(Collections.reverseOrder())))
.collect(Collectors.toList());

How to sort an objects list based on the attribute in the lists

@Data
public class Item {

private int notificationId;
private List<Wise> areaWise;
private List<Wise> sensorWise;
private List<Wise> regionWise;

@Data
public static class Wise {
private int id;
private int threshold;
private int headCount;
private int pecentage;
}
}

class Test {
static void main() {
ArrayList<Item> items = new ArrayList<>(10);

items.sort(Comparator.comparingInt(
item ->
Stream.of(item.getAreaWise(), item.getSensorWise(), item.getRegionWise())
.flatMapToInt(wises -> wises.stream().mapToInt(Item.Wise::getPecentage))
.max().orElse(Integer.MIN_VALUE)
));
}
}


Related Topics



Leave a reply



Submit