Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Kieran Robinson
Kieran Robinson
9,411 Points

Find the closest value in an array

Hello, I have an array of 25 float values, I wish to take a number entered by the user into a UITextField and then loop through the array to find the nearest value. I had this working with 'binary searching' (was on stack overflow) however this only worked when the numbers were in order, does anyone have any ideas? Thanks Kieran

Amit Bijlani, Stone Preston, Ben Jakuben, Ash Furrow, Douglass Turner

Kieran Robinson
Kieran Robinson
9,411 Points

my array is not sorted*

6 Answers

Hi Kieran,

Is there a reason you can't sort it? Do these 25 float values change?

Assuming it's not desirable/efficient to sort it -

One thing you can do is have 2 variables, 1 to hold the current smallest difference and the other to hold the current closest number or it's index (whichever you need)

You can first get the difference between the first float and the user number and assume that's the closest number. Store the difference and the index in those 2 variables.

Then loop through the remainder checking the difference on each one and seeing if that is smaller than the current smallest difference. If it is, then you update your 2 variables with the new smallest difference and the index of that new closest number.

I don't have any ios experience but here's a javascript example of what I'm talking about:

values = [36.32, 4.5, 2.5, 7.9, -6.5, 13.6];

userNum = 5.6; //This is coming from user input

smallestDiff = Math.abs(userNum - values[0]);
closest = 0; //index of the current closest number

for (i = 1; i < values.length; i++) {
  currentDiff = Math.abs(userNum - values[i]);
  if (currentDiff < smallestDiff) {
    smallestDiff = currentDiff;
    closest = i;
  }
}

console.log(values[closest]); //logs 4.5

Hopefully you can adapt to your code.

A binary search on a sorted array will be faster than this. This solution is going through the entire array every time.

So again, if you have some reason you can't sort or maybe the 25 values are changing and you would have to continually resort then this solution might help you.

so then alloc a tempArray and set it equal to the sorted array. perform a binary search algorithm on the tempArray and retrieve your value from that?

Kieran Robinson
Kieran Robinson
9,411 Points

would a binary search work on the tempArray as it also wouldn't be sorted?

Kieran Robinson
Kieran Robinson
9,411 Points

Thank you Jason Anello !! Your answer is very helpful and I'm trying my best to adapt the code i have written. I am working on a colour match app, and have an array of red green and blue values that aren't meant to be in order, would I have to repeat this for loop each time to locate the closest value of red, green, and blue separately? Kieran

Hi Kieran,

Sorry for the delayed response.

This changes the problem a bit. I had to do a little research here because I've never dealt with color matching. I'm also trying to get a codepen demo going as a sort of proof of concept.

Can you clarify what it is you're doing and what the user is entering? As I understand it now, you have 25 colors stored in an array with rgb components and the user is going to enter a color and you want to find which of the 25 colors matches the closest to the user color. Is that correct? I don't see now where floats fit into this.

I don't think your idea will work on running each value separately through the loop. You probably will need a color matching algorithm.

Based on the little research I've done there doesn't seem to be one true correct answer on how to determine how close 2 colors are. There are different algorithms based on different color models from what I could gather so far.

I came across several stackoverflow answers saying you can't or don't want to do this with rgb but then I found this paper which seams to suggest you can do it with rgb: http://www.compuphase.com/cmetric.htm

I had to gloss over the text but about 3 quarters of the way down there is a C code snippet of the algorithm. That is probably as good a place as any to start with. Are you able to use straight C in an ios app?

Disclaimer: I would check the licensing though and make sure you are allowed to use this in your app I guess I better make sure I can use it in the codepen demo too.

The color is stored in a struct. You pass in 2 colors and it gives you back a difference. You should be able to use this with the code I already gave you. Instead of getting the absolute value of the difference between 2 floats you would call this function instead and pass in 2 colors.

So this line:

smallestDiff = Math.abs(userNum - values[0]);

Would become something like this:

smallestDiff = colorDistance (userColor, colors[0]);

And it would be a similar change for the one inside the for loop.

I hope this gets you going in the right direction! Let me know if I've completely misunderstood your problem.

If you need help with getting this into code you can use in your ios app then I would recommend that you start a new thread on this but clearly explain that this is a color matching app and you need help with getting a couple of javascript and c functions converted over. You can link to this thread so everyone has the background on it.

Kieran Robinson
Kieran Robinson
9,411 Points

Hello Jason Anello, Firstly thank you for the awesome reply, Basically, the user will take a photo of, for example, their wall in their living room. The app then finds an average colour of this image (using http://www.bobbygeorgescu.com/2011/08/finding-average-color-of-uiimage/) and i want to compare that to a list of rgb values that i have hard coded in an array (red array, green array, and blue array). I need to take the average colour of the image, iterate through red, green and blue array and get the closest value for each rgb element of the image the user takes. with those closest values, ill pick the closest colour from the array. Does this clarify anything?

Also, that codepen demo would be great! Thanks a lot,

kieran

You're welcome although I think I'm off on the solution.

I'm still confused about the float values. Wouldn't your r, g, b values be integers in the range 0 to 255?

I understand all the way up to getting a color from the image. I'm confused about your 3 arrays though.

Are the 3 arrays that you have independent of each other? Where you might take the 1st element from red, the 10th element from green, and the 14th element from blue as an example.

Or is it such that the 1st element from each one makes up the 1st color, the 2nd element from each one is the 2nd color, etc...

In other words, do you have 25 colors or can there be any combination of the red, green, and blue arrays where you would actually have 25 * 25 * 25 possible colors?

The solution I was describing was as if you had 25 colors and needed to find the closest match.

But are you saying you want to find the closest red value independent of the green and blue values? and then do the same for green and blue...

Kieran Robinson
Kieran Robinson
9,411 Points

I haven't been very clear in my question I'm sorry Jason Anello, I had approached my issue in the complete wrong way and I've managed to fix my problem. I now have an array of floats called difference (its created like this http://stackoverflow.com/questions/1767941/objective-c-find-closest-color-rgb-match). The smaller the float, the closer match to the colour it is. my problem is that i need to be able to loop through the array to find the smallest float. any ideas? Thanks Kieran

Kieran Robinson
Kieran Robinson
9,411 Points

Hello, to anyone looking to find the smallest value in the array (as i did in the end), this worked for me, doesn't matter if its ordered or not!

float minFloat = [[self.differenceValueArray valueForKeyPath:@"@min.floatValue"] floatValue];
float max = [[self.differenceValueArray valueForKeyPath:@"@max.floatValue"] floatValue];

NSLog(@"minimum = %f", minFloat);

Thanks to Jason Anello, you really helped with this one mate! Kieran

You're welcome.

Glad you got it sorted out!