Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Finding the Index of the lowest valued element in an array?

Discussion in 'Scripting' started by Genkidevelopment, Feb 1, 2015.

  1. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    I'm sorry if this is a question that has been asked before, but after reading several explanations I am still struggling to understand, perhaps someone can offer a explanation of how this is done..

    MyArray [10]

    MyArray [0] = 1position.z
    MyArray [1] = 2position.z
    MyArray [2] = 3position.z... Etc...

    I am able to calculate the lowest value, but I need to know 'what' index it is, be it [4] , [7] or whatever it may be!

    Many thanks if you take the time to help

    Peace
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    Loop over the array comparing the value to the last lowest value, if it's lower save off the index, do this all the way too the end. Once at the end, the lowest of values will be the last index you stored.

    Code (csharp):
    1.  
    2. public int GetIndexOfLowestValue(float[] arr)
    3. {
    4.     float value = float.PositiveInfinity;
    5.     int index = -1;
    6.     for(int i = 0; i < arr.Length; i++)
    7.     {
    8.         if(arr[i] < value)
    9.         {
    10.             index = i;
    11.             value = arr[i];
    12.         }
    13.     }
    14.     return index;
    15. }
    16.  
     
    Beetruth and Tonymotion like this.
  3. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    That makes perfect sense... So, we are creating a separate function to do this job... named 'GetIndexOfLowestValue'... Now about to try it, and as you mention looping through it, I'm starting to see what all the i's and i++'s are doing... Thanks a lot :D
     
  4. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    I don't understand where to put this!?... I tried placing it in the FixedUpdate and got an unexpected 'public' error... I have tried placing it above the start function, and it no longer gives me an error, but I see no result! If I try to 'print' 'index'?

    what does the return 'index' do and how can i 'see' it?
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    It's a function, you have to call the function. This is a fundamental part of programming... you should probably google about it.
     
  6. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Thanks for the answer and yes, I am constantly trying to learn and understand with more clarity... But I have no teacher, I am having to self-learn!
     
  7. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    of course, that also returns the min value, not the index of the min value...

    but, yes OP, you should check out the System.Linq namespace, it has all sorts of little goodies.
     
  9. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    With a list:
    int index = blahList.IndexOf(blahList.Min());

    Other enumerable types without similar methods can use linq to do it in a single line as well, rather than writing a method for each way you want to search an array.
     
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    true, I agree, I use linq rather frequently

    but now you did it with a list, not an array, like OP asked.

    And also your search is now O(n * 2) in efficiency, rather than O(n) with a single loop. A single line doesn't necessarily mean a more efficient search.
     
  11. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    Like I said, other IEnumerables can use other methods. Just presenting examples and options.

    Definitely true about the efficiency thing. Using linq usually isn't the most efficient, but it sure is handy.
     
  12. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Thanks a lot for the answers, tips and discussions... I appreciate all of your input... Learning code is a dream I am trying to achieve so all discussions shed light on things I haven't yet grasped!

    When talking of O(n) - we are using that expression to gauge how performance heavy an option is?...

    Now got to head back to work, but upon returning home I shall start the quest again!

    Peace all :D
     
  13. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Sorry to still go on about the same noob questions... But...

    This would be an ideal piece of code to create in a separate script? Then, whenever we need to return the 'lowest valued index of an array', we can simply call that script from another script? By calling it's function...? Is this the correct understanding?

    Thanks
     
  14. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    I usually have 'util' classes for generalized functions.

    It's a static class, that does NOT inherit from MonoBehaviour, with static functions that can be called.

    Here is several util classes I have:
    https://code.google.com/p/spacepupp...n/trunk/SpacepuppyBase/Utils%3Fstate%3Dclosed

    Here is one that contains 'extension methods' for collections:
    https://code.google.com/p/spacepupp...uppyBase/Utils/IEnumerableExtensionMethods.cs

    an extension method is a static method that can be syntactically called on an object like an instance method... it's just syntax sugar... see this article about them:
    https://msdn.microsoft.com/en-us/library/bb383977.aspx

    You don't have to write them as extension methods though. As you can see here with MathUtil:
    https://code.google.com/p/spacepupp...browse/trunk/SpacepuppyBase/Utils/MathUtil.cs
     
    Genkidevelopment likes this.
  15. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Thanks for the info - I took a quick tour around your website and saw how you were using tags to find the root of gameobjects... Cool stuff - way over my head for now... For the first time in a month of learning, this problem has held me up for more than a session... :(
     
  16. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186

    LordOfDuct... Do you mind if I use the code and ask someone to explain it step by step... I almost get it, but as it is I am about to put my keyboard through the monitor :( Cant remember myself getting this frustrated about anything in a very long time!
     
  17. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    Sure, I'll explain it step by step for you if you'd like.

    Code (csharp):
    1.  
    2. //declare a function that accepts a float array, and will return an index
    3. public int GetIndexOfLowestValue(float[] arr)
    4. {
    5.     //here we declare a variable to store the lowest found value. We default to positive infinity because no value was found, and all values are less than pos infinity
    6.     float value = float.PositiveInfinity;
    7.     //here we declare our found index, no index has been found, so we set it to -1. -1 being the common standard value for an unknown index
    8.     int index = -1;
    9.     //now lets loop over every entry of the array. We loop from index 0 to the last index.
    10.     for(int i = 0; i < arr.Length; i++)
    11.     {
    12.         //if the value at this index is less than the last found small value, then we have an even smaller value
    13.         if(arr[i] < value)
    14.         {
    15.             //store the index of this newly found smaller value
    16.             index = i;
    17.             //also store that value for testing against the rest of the values
    18.             value = arr[i];
    19.         }
    20.     }
    21.     //once this loop has checked every value, it will contain the smallest value/index in the array
    22.    
    23.     //return our found index
    24.     return index;
    25. }
    26.  
    The principal works like so... lets say we have an array:

    [5, 3, 9, 6, 2, 4]

    as we loop

    we test entry 0, 5 is less than +inf, so we store 0 into 'index' and 5 into 'value'

    we test entry 1, 3 is less than 5, so we store 1 into 'index' and 3 into 'value'

    we test entry 2, 9 is NOT less than 3, so 'index' remains 1, and 'value' remains 3

    we test entry 3, 6 is NOT less than 3, so 'index' remains 1, and 'value' remains 3

    we test entry 4, 2 is less than 3, so we store 4 into 'index', and 2 into 'value'

    we test entry 5, 4 is NOT less than 2, so 'index' remains 4, and 'value' remains 2

    we're done, the index is 4, return 4
     
    Genkidevelopment likes this.
  18. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Bless you for taking the time to do this... I'm sure you are a very busy person and probably have better/more productive things to do and I sincerely applaud your efforts in helping me! I have grasped exactly what you have just explained... the principle of looping through each value and storing ONLY if the criteria IS met... Here are the things I don't fully fathom...

    Code (csharp):
    1.  3. public int GetIndexOfLowestValue(float[] arr)
    Here the word 'arr' and ALL subsequent 'arr's within this piece of code (method?) would be replaced with the actual name of the array we want a result from? In my case that would be...

    Code (csharp):
    1.  public float [] HClosestPlayerToBall;
    ... As that is the name of the array I want a result from... As long as this array is 'Public' we can sub it into the 'GetIndexOfLowestValue' Method?

    So in my case, line 3 would look like:

    Code (csharp):
    1.  3. public int GetIndexOfLowestValue(float[] HClosestPlayerToBall)
    I try to 'print (index);' I get no errors, but no print either... I feel like I am not calling the function?

    Here is the code that I have... I don't like to ask, but I am going to because I feel after seeing how it's done, the final pieces of this particular jigsaw will fall into place... Where/how/why do I get your function of 'GetIndexOfLowestValue' into my code...?

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Linq;
    5. public class HomeStateMachine : MonoBehaviour
    6. {
    7. public Transform Ball;
    8.  
    9. /*
    10. public Transform  HPlayer1 = HP1;
    11. public float DifXH1;
    12. public float DifZH1;
    13. public float H1BallDistanceSquared;
    14. public float H1BallDistance; */
    15.  
    16. public Transform HPlayer2;
    17. private float DifXH2;
    18. private float DifZH2;
    19. private float H2BallDistanceSquared;
    20. public float H2BallDistance;
    21. public float H2BallDirection;
    22. public Transform HPlayer3;
    23. private float DifXH3;
    24. private float DifZH3;
    25. private float H3BallDistanceSquared;
    26. public float H3BallDistance;
    27. public float H3BallDirection;
    28.  
    29. public Transform HPlayer4;
    30. private float DifXH4;
    31. private float DifZH4;
    32. private float H4BallDistanceSquared;
    33. public float H4BallDistance;
    34. public float H4BallDirection;
    35. public Transform HPlayer5;
    36. private float DifXH5;
    37. private float DifZH5;
    38. private float H5BallDistanceSquared;
    39. public float H5BallDistance;
    40. public float H5BallDirection;
    41. public Transform HPlayer6;
    42. private float DifXH6;
    43. private float DifZH6;
    44. private float H6BallDistanceSquared;
    45. public float H6BallDistance;
    46. public float H6BallDirection;
    47. public Transform HPlayer7;
    48. private float DifXH7;
    49. private float DifZH7;
    50. private float H7BallDistanceSquared;
    51. public float H7BallDistance;
    52. public float H7BallDirection;
    53. public Transform HPlayer8;
    54. private float DifXH8;
    55. private float DifZH8;
    56. private float H8BallDistanceSquared;
    57. public float H8BallDistance;
    58. public float H8BallDirection;
    59. public Transform HPlayer9;
    60. private float DifXH9;
    61. private float DifZH9;
    62. private float H9BallDistanceSquared;
    63. public float H9BallDistance;
    64. public float H9BallDirection;
    65. public Transform HPlayer10;
    66. private float DifXH10;
    67. private float DifZH10;
    68. private float H10BallDistanceSquared;
    69. public float H10BallDistance;
    70. public float H10BallDirection;
    71. public Transform HPlayer11;
    72. private float DifXH11;
    73. private float DifZH11;
    74. private float H11BallDistanceSquared;
    75. public float H11BallDistance;
    76. public float H11BallDirection;
    77. ///====================================================
    78. public float [] HClosestPlayerToBall; //Creating Array to find closest player to ball
    79. public Transform HomePressingArea; //Calling for pressing area so we can see if this function needs calculating
    80. public float Closest; // Only when the ball is in the pressing area should we worry who is the closest player to the ball!
    81.  
    82. void Start ()
    83. {
    84. HClosestPlayerToBall = new float [10]; // Initialising the array with 10 slots ** GK NOT INCLUDED YET **
    85. }
    86.  
    87. void FixedUpdate ()
    88. {
    89.  
    90. /*  GoalKeeper  *DifXH1 = HPlayer1.position.x - Ball.position.x;
    91. DifZH1 = HPlayer1.position.z - Ball.position.z;
    92. H1BallDirection = Mathf.Atan2 (DifXH1, DifZH1) * 180 / Mathf.PI;
    93. H1BallDistanceSquared = (DifXH1 * DifXH1) + (DifZH1 * DifZH1);
    94. H1BallDistance = Mathf.Sqrt (H1BallDistanceSquared); */
    95. DifXH2 = HPlayer2.position.x - Ball.position.x; // Using pythagarus theory hence to calculate distances
    96. DifZH2 = HPlayer2.position.z - Ball.position.z;
    97. H2BallDirection = Mathf.Atan2 (DifXH2, DifZH2) * 180 / Mathf.PI;
    98. H2BallDistanceSquared = (DifXH2 * DifXH2) + (DifZH2 * DifZH2);
    99. H2BallDistance = Mathf.Sqrt (H2BallDistanceSquared);
    100. DifXH3 = HPlayer3.position.x - Ball.position.x;
    101. DifZH3 = HPlayer3.position.z - Ball.position.z;
    102. H3BallDirection = Mathf.Atan2 (DifXH3, DifZH3) * 180 / Mathf.PI;
    103. H3BallDistanceSquared = (DifXH3 * DifXH3) + (DifZH3 * DifZH3);
    104. H3BallDistance = Mathf.Sqrt (H3BallDistanceSquared);
    105. DifXH4 = HPlayer4.position.x - Ball.position.x;
    106. DifZH4 = HPlayer4.position.z - Ball.position.z;
    107. H4BallDirection = Mathf.Atan2 (DifXH4, DifZH4) * 180 / Mathf.PI;
    108. H4BallDistanceSquared = (DifXH4 * DifXH4) + (DifZH4 * DifZH4);
    109. H4BallDistance = Mathf.Sqrt (H4BallDistanceSquared);
    110. DifXH5 = HPlayer5.position.x - Ball.position.x;
    111. DifZH5 = HPlayer5.position.z - Ball.position.z;
    112. H5BallDirection = Mathf.Atan2 (DifXH5, DifZH5) * 180 / Mathf.PI;
    113. H5BallDistanceSquared = (DifXH5 * DifXH5) + (DifZH5 * DifZH5);
    114. H5BallDistance = Mathf.Sqrt (H5BallDistanceSquared);
    115. DifXH6 = HPlayer6.position.x - Ball.position.x;
    116. DifZH6 = HPlayer6.position.z - Ball.position.z;
    117. H6BallDirection = Mathf.Atan2 (DifXH6, DifZH6) * 180 / Mathf.PI;
    118. H6BallDistanceSquared = (DifXH6 * DifXH6) + (DifZH6 * DifZH6);
    119. H6BallDistance = Mathf.Sqrt (H6BallDistanceSquared);
    120. DifXH7 = HPlayer7.position.x - Ball.position.x;
    121. DifZH7 = HPlayer7.position.z - Ball.position.z;
    122. H7BallDirection = Mathf.Atan2 (DifXH7, DifZH7) * 180 / Mathf.PI;
    123. H7BallDistanceSquared = (DifXH7 * DifXH7) + (DifZH7 * DifZH7);
    124. H7BallDistance = Mathf.Sqrt (H7BallDistanceSquared);
    125. DifXH8 = HPlayer8.position.x - Ball.position.x;
    126. DifZH8 = HPlayer8.position.z - Ball.position.z;
    127. H8BallDirection = Mathf.Atan2 (DifXH8, DifZH8) * 180 / Mathf.PI;
    128. H8BallDistanceSquared = (DifXH8 * DifXH8) + (DifZH8 * DifZH8);
    129. H8BallDistance = Mathf.Sqrt (H8BallDistanceSquared);
    130. DifXH9 = HPlayer9.position.x - Ball.position.x;
    131. DifZH9 = HPlayer9.position.z - Ball.position.z;
    132. H9BallDirection = Mathf.Atan2 (DifXH9, DifZH9) * 180 / Mathf.PI;
    133. H9BallDistanceSquared = (DifXH9 * DifXH9) + (DifZH9 * DifZH9);
    134. H9BallDistance = Mathf.Sqrt (H9BallDistanceSquared);
    135. DifXH10 = HPlayer10.position.x - Ball.position.x;
    136. DifZH10 = HPlayer10.position.z - Ball.position.z;
    137. H10BallDirection = Mathf.Atan2 (DifXH10, DifZH10) * 180 / Mathf.PI;
    138. H10BallDistanceSquared = (DifXH10 * DifXH10) + (DifZH10 * DifZH10);
    139. H10BallDistance = Mathf.Sqrt (H10BallDistanceSquared);
    140. DifXH11 = HPlayer11.position.x - Ball.position.x;
    141. DifZH11 = HPlayer11.position.z - Ball.position.z;
    142. H11BallDirection = Mathf.Atan2 (DifXH11, DifZH11) * 180 / Mathf.PI;
    143. H11BallDistanceSquared = (DifXH11 * DifXH11) + (DifZH11 * DifZH11);
    144. H11BallDistance = Mathf.Sqrt (H11BallDistanceSquared);
    145. //Filling the array with the player distances to ball
    146. HClosestPlayerToBall [0] = H2BallDistance;
    147. HClosestPlayerToBall [1] = H3BallDistance;
    148. HClosestPlayerToBall [2] = H4BallDistance;
    149. HClosestPlayerToBall [3] = H5BallDistance;
    150. HClosestPlayerToBall [4] = H6BallDistance;
    151. HClosestPlayerToBall [5] = H7BallDistance;
    152. HClosestPlayerToBall [6] = H8BallDistance;
    153. HClosestPlayerToBall [7] = H9BallDistance;
    154. HClosestPlayerToBall [8] = H10BallDistance;
    155. HClosestPlayerToBall [9] = H11BallDistance;
    156.  
    157. Closest = HClosestPlayerToBall.Min ();
    158. print ("HClosestPlayerToBall is :" + Closest ); // Distance of lowest value NOT index...
    159.  
    160. //// Need to sort array and find index of lowest value
    161. }
    162. }
    163.  
     
  19. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    Array's are reference types, you can create a function with an arbitrarily named variable, and if you pass the desired array into it, that parameter variable will reference the same array.

    Code (csharp):
    1.  
    2. public class HomeStateMachine : MonoBehaviour
    3. {
    4.  
    5.     void FixedUpdate()
    6.     {
    7.         ... all your code about
    8.      
    9.         var indexOfLowest = ArrayUtil.GetIndexOfLowestValue(HClosestPlayerToBall);
    10.     }
    11.  
    12. }
    13.  
    14. public static class ArrayUtil
    15. {
    16.     public static int GetIndexOfLowestValue(float[] arr)
    17.     {
    18.         float value = float.PositiveInfinity;
    19.         int index = -1;
    20.         for(int i = 0; i < arr.Length; i++)
    21.         {
    22.             if(arr[i] < value)
    23.             {
    24.                 index = i;
    25.                 value = arr[i];
    26.             }
    27.         }
    28.         return index;
    29.     }
    30. }
    31.  
    This is one critical aspect of object oriented programming. The idea you can 'reference' an object, and that object is unique from other objects.

    We have a class of type 'Array', but we can have 10 distinct arrays, and we can move them around our program with out making copies of them.

    This goes for all the custom classes you define as well.
     
    Genkidevelopment likes this.
  20. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    I'm not going to lie, I still don't fully understand, although I do now have the code working perfectly thanks to your continued help! :D and with another nights rest and re-evaluation tomorrow I feel it's close...

    Thing is, I think It's a trying to run before walking type affair... I have dived straight into the deep end and finally run out of puff!!! I promise to go back and review all of the tutorials again so your efforts are not wasted in a 'paint by numbers' kind of way...

    Once again, thanks for all the help and I hope you are having/had a good day...

    Peace
     
  21. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,377
    No problems.

    Honestly, the concept of object identity is often the biggest hurdle most people have when picking up an object oriented language. It took me a while to wrap my head around it as well when I started years back.

    The artist on my project (see my website www.jupiterlighthouse.com, he's the long haired weirdo standing with me at the speech we did last week), he's currently attempting to learn to program, and it too is the very concept he's having a hard time with as well.
     
    Genkidevelopment likes this.
  22. Genkidevelopment

    Genkidevelopment

    Joined:
    Jan 2, 2015
    Posts:
    186
    Haha... I'm a long haired weirdo as well!
    How long have you been programming? I'm an engineer by trade, and it's very logic based, hence a lot of what I am seeing with programming is easily understood, but like anything, it takes time to grasp the concepts and terminology, and that's half the battle right!?

    I also make music/songwriter... Indie stuff, acoustic guitars etc... If I can ever be of help, please ask... ;)