Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by greatness · Jun 14, 2016 at 06:06 AM · scripting beginnerscriptingbasics

What is IComparable, CompareTo function, and ArrayList.Sort()

:| Read the title above. P.S. how can we sort an arraylist from greatest to least based on one variable?

I want to know this because on the Procedural Cave Generation tutorial, there is this code bit.

 // [...]
     void ProcessMap() {
         // [...]
         List<Room> survivingRooms = new List<Room> ();
         // [...]
         
         survivingRooms.Sort ();
         survivingRooms [0].isMainRoom = true;
         survivingRooms [0].isAccessibleFromMainRoom = true;
         
         ConnectClosestRooms (survivingRooms);
     }
     
     struct Coord {
         public int tileX;
         public int tileY;
         
         public Coord(int x, int y) {
             tileX = x;
             tileY = y;
         }
     }
     
     
     class Room : IComparable<Room> {
         public List<Coord> tiles;
         public List<Coord> edgeTiles;
         public List<Room> connectedRooms;
         public int roomSize;
         public bool isAccessibleFromMainRoom;
         public bool isMainRoom;
         
         public Room() {
         }
         
         public Room(List<Coord> roomTiles, int[,] map) {
             tiles = roomTiles;
             roomSize = tiles.Count;
             connectedRooms = new List<Room>();
             
             edgeTiles = new List<Coord>();
             foreach (Coord tile in tiles) {
                 for (int x = tile.tileX-1; x <= tile.tileX+1; x++) {
                     for (int y = tile.tileY-1; y <= tile.tileY+1; y++) {
                         if (x == tile.tileX || y == tile.tileY) {
                             if (map[x,y] == 1) {
                                 edgeTiles.Add(tile);
                             }
                         }
                     }
                 }
             }
         }
         
         public void SetAccessibleFromMainRoom() {
             if (!isAccessibleFromMainRoom) {
                 isAccessibleFromMainRoom = true;
                 foreach (Room connectedRoom in connectedRooms) {
                     connectedRoom.SetAccessibleFromMainRoom();
                 }
             }
         }
         
         public static void ConnectRooms(Room roomA, Room roomB) {
             if (roomA.isAccessibleFromMainRoom) {
                 roomB.SetAccessibleFromMainRoom ();
             } else if (roomB.isAccessibleFromMainRoom) {
                 roomA.SetAccessibleFromMainRoom();
             }
             roomA.connectedRooms.Add (roomB);
             roomB.connectedRooms.Add (roomA);
         }
         
         public bool IsConnected(Room otherRoom) {
             return connectedRooms.Contains(otherRoom);
         }
         
         public int CompareTo(Room otherRoom) {
             return otherRoom.roomSize.CompareTo (roomSize);
         }
     }
 }


Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Jun 15, 2016 at 10:02 AM

Even @tanoshimi's answer does already answer your original question, here are a few more details.

The generic List class has a Sort method to sort the elements of the List. It comes with 4 overloads:

  • Sort()

  • Sort(IComparison)

  • Sort(IComparer)

  • Sort(int, int, IComparer)

The first Sort overload takes no parameters at all. It does only work for element types which are comparable either by default (primitive types like int, float, string) or by implementing the IComparable<T> interface.

In the example code you posted that's the version that is used. As you can see when you look at the documentation of IComparable, it only has one method that need to be implemented: CompareTo. This method has only one parameter and it get passed another object / element to which this object should be compared to. The method return an integer which indicates the relationship between those two objects. It basically can return 3 different values:

  • A value less than 0 (usually "-1")

  • "0" (zero)

  • A value greater than 0 (usually "1")

When CompareTo returns a negative value, that means the object should appear before the "other" object in the sorted list.
When CompareTo return 0 it means both objects are equal, so it doesn't care which one goes first.
When CompareTo return a positive value, that means the object should appear after the "other" object.

As i said primitive types like "int" also implement this interface and can be sorted natively. Sorting always sort from the lowest to the greatest value by default. If you want to sort the values the other way round you just have to "invert" the return value of CompareTo. This can be done by literaly inverting the value by placing a "-" infront of the return value, or by swapping the two compared objects. The second solution is what has beed used in your code example. So instead of comparing the roomSize of this room with the roomSize of the other room, he swapped the two variables.

So this:

 return otherRoom.roomSize.CompareTo (roomSize);

would be the same as:

 return -roomSize.CompareTo (otherRoom.roomSize);

The Sort method will internally iterate through all elements and call the CompareTo method of the elements inside the List in order to determine the order of the elements.

The other 3 overloads work the same way, but they don't require the element type to implement the IComparable interface. Instead you either have to pass a delegate (method reference) to a method that can compare two elements of your List:

 private static int Compare(Room room1, Room room2)
 {
     return room2.roomSize.CompareTo (room1.roomSize);
 }

Or you have to pass a "comparer object" which does the comparison of two elements. It's basically the same as using a delegate, but the method has to be inside an object that implements the IComparer interface. This might be useful when you have external dependencies that you need during your comparing operation. For example to sort the elements based on a threshold value. Such a comparer object can only dynamically handle the sort order by checking a bool member variable. However those are more advanced things which you only need when you want to sort the list in many different ways.

To sum up:

  • The IComparable interface can define the default sorting order of a certain class / struct.

  • Passing a IComparison delegate to the Sort method is an easy way to specify a custom sorting logic

  • Creating a seperate IComparer object can be used when a more advanced sorting is required.

Note: instead of explicitly creating a comparer object you can also use a lambde expression / anonymous method / closure. Those will automatically create a hidden class which serves the same purpose as a comparer object due to the ability to reference variables from the outer scope.

 // passing a lambda expression which does the same as the CompareTo method above
 list.Sort((a,b)=>b.roomSize.CompareTo(a.roomSize));

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
3

Answer by tanoshimi · Jun 14, 2016 at 06:17 AM

Icomparable is the interface for comparable objects and CompareTo is the function called when determining how two objects should be sorted.

Sorting simple datatypes like numbers is easy and fairly unambiguous. 15 > 7 > 2 > 0. So, if you were to sort a list containing the elements {15, 2, 7, 15, 0}, the result would be 0,2,7,15,15.

But what if you were to sort a list of a custom class of colours say: {black, red, white, blue}? Is white > black? Is dog > cat? That's why you'd need to override the CompareTo function to specify how you want the comparison to operate.

Incidentally, Arraylist is very old and not very good. I'd recommend you use generic List or native arrays if your collections are of fixed size.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image greatness · Jun 14, 2016 at 10:45 PM 0
Share

Umm...makes some sense. However, I was talking about how the IComparable interface is used in the Procedural Cave Generation tutorial. How did Sebastian Lague order the numbers from greatest to least?

avatar image Bunny83 greatness · Jun 15, 2016 at 12:07 AM 1
Share

I was talking about how the IComparable interface is used in the Procedural Cave Generation tutorial

Uhm, you might want to re-read your own question carefully. You didn't talk anything about any tutorial or procedural cave generation. You ask a relatively clear and short question and this answer answers that question very well. If you want a more specific answer, ask a more specific question which should be a bit longer than a single line.

I have never looked at any tutorial so i have no idea what you talk about. You should at least provide some background information and at least a link to the exact section of the tutorial. That's also a question that doesn't belong to the normal UnityAnswers space. IComparable and the Sort method is ordinary .NET / $$anonymous$$ono functionality.

For plain support questions you should post your question in the help room.

avatar image greatness Bunny83 · Jun 15, 2016 at 12:36 AM 0
Share

I did your suggestions. And i did already put this in the help section. I could have sworn I did...

avatar image greatness · Jun 15, 2016 at 12:35 AM 0
Share

P.S. I know this may be asking too much, but I would understand the concept much better if you added sample code with comments :)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Timer wont work 0 Answers

Make enemy patrol without Nav Points? 0 Answers

random spawn enemy problem 0 Answers

Help with Changing the Sprite image in the Script 0 Answers

this script is missed up help? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges