0

I would like to sort a list by referring to the elements being compared. So if one element has attribute X to other element, I want it first.

Simple example:

class Apple:
    def can_eat(self, other):
        return False


class Human:
    def can_eat(self, other):
        # can eat humans or apples. No other food, because it's an example
        if isinstance(other, Human):
            return True
        return isinstance(other, Apple)

class Thing:
    def can_eat(self, other):
        return False


apple = Apple()
human = Human()

things = [apple, human, apple]
things.sort(?)  # I'd want human before or after apple (depending on reverse)

Is there a way I can sort a list on this in python?

To be clear: The problem I have is that using something like this answer: sort list of objects by return of object method

does not work for me, as I still don't see how to access both objects, i.e. how to specify the lambda function to, when comparing human vs. apple, call human.can_eat(apple) or vice versa.

Simply closing the question as "related" did not explain this to me, so please either close with a question that does answer mine, or fill in the gaps. Thank you.

bytepusher
  • 1,568
  • 10
  • 19
  • Sure, there's a related question. It's not the same question, though. Explaining to me _how_ it is the same would be helpful, simply closing it is not. Seems like a superficial read, then close to me – bytepusher Jul 11 '22 at 11:58
  • Why do you need to compare "relative to other elements"? It just sounds like you want to sort all elements that return `True` from `can_eat` before elements that return `False`. – deceze Jul 11 '22 at 11:58
  • But the method return changes based on what I'm comparing against. There is no "global" can_eat, which is why the related question doesn't work – bytepusher Jul 11 '22 at 11:59
  • Then you'll need to explain your logic more. How would you compare what to what? If you want to sort something, you need to potentially compare everything with everything, and `can_eat` may return `True` or `False` for the same object. How can any absolute order be established this way? – deceze Jul 11 '22 at 12:00
  • This is possible in other languages, and distinct from the solution proposed. As an example in perl: `sort{ $a->can_eat($b) } @things` with can_eat modified to return -1,0,1 accordingly – bytepusher Jul 11 '22 at 12:00
  • That Perl example would result in some arbitrary random order, depending on the implementation details of `sort` and in what order it happens to populate `$a` and `$b`. – deceze Jul 11 '22 at 12:01
  • The method returns true or false for each pair of objects. It may return False for several combinations. How does this stop an "absolute order" from being established more than another method that returns False, True sometimes? Maybe even random? – bytepusher Jul 11 '22 at 12:01
  • No, $a and $b are reserved for sorting. – bytepusher Jul 11 '22 at 12:02
  • I think you're trying to discuss the question in the comments. I would prefer an answer. This seems to me like you're trying to justify your close as "it's related", when you've not yet told me at all why it's the same. I've not said "it's not related", I've said "it's not the same" – bytepusher Jul 11 '22 at 12:03
  • Explain in English how you want to sort the items relative to each other. – deceze Jul 11 '22 at 12:03
  • OK, yeah, no, the duplicate isn't perfectly related. But the best I can offer is to close the question as unclear instead, since the logic is not apparent. – deceze Jul 11 '22 at 12:04
  • I want object a to be before object b, if a.can_eat(b). This can be solved. I would like to know how. – bytepusher Jul 11 '22 at 12:04
  • `a` and `b` in sorting algorithm stand for any two arbitrary values from your set. If you substitute them with two `Human` instances the result is `False`, but if you have a `Human` and `Apple` pair, the result is `True`, **for the same `Human` object.** Where should that `Human` appear in the list now, given one `False` and one `True` result? – deceze Jul 11 '22 at 12:06
  • And regarding absolute order: A method being used with a methodcaller also may return the same value for different objects. That just means there's no guarantee for how they're sorted, that's a normal problem with sorting. – bytepusher Jul 11 '22 at 12:06
  • @deceze. OP is looking to replace a general purpose comparator, and proposed a situation where it's unclear how a key could be replaced by a comparator – Mad Physicist Jul 11 '22 at 12:06
  • @bytepusher. It's not a normal problem at all. – Mad Physicist Jul 11 '22 at 12:07
  • I should probably have improved the example by adding a line that humans can eat humans – bytepusher Jul 11 '22 at 12:07
  • @bytepusher. Yes, for realism. – Mad Physicist Jul 11 '22 at 12:08
  • So it not being a "normal" problem means it must be closed then? – bytepusher Jul 11 '22 at 12:09
  • More fitting dupe: https://stackoverflow.com/a/57003713/476 – deceze Jul 11 '22 at 12:10
  • from functools import cmp_to_key sorted(mylist, key=cmp_to_key(compare)) seems to be what I was looking for, thank you. – bytepusher Jul 11 '22 at 12:13

0 Answers0