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
Best Way to Convert String to Bytes in Python 3
Saving an Object (Data Persistence)
Can a Variable Number of Arguments Be Passed to a Function
Finding Local Ip Addresses Using Python'S Stdlib
Permanently Add a Directory to Pythonpath
Read Subprocess Stdout Line by Line
Django Template How to Look Up a Dictionary Value With a Variable
How to Convert an Rgb Image into Grayscale in Python
How to Use Pickle to Save a Dict (Or Any Other Python Object)
Remove Specific Characters from a String in Python
Why Should Exec() and Eval() Be Avoided
How to Install Python Packages [Ssl: Tlsv1_Alert_Protocol_Version]
How to Sort a Dataframe in Python Pandas by Two or More Columns
Error Message: "'Chromedriver' Executable Needs to Be Available in the Path"
How to Hide Output of Subprocess