0

I have searched around trying to find a similar problem, however I do not know the correct wording. I have an array of CGFloats and then a separate saved CGFloat. I want to check if the single CGFloat is between the values stored in the array.

I currently have this in a loop starting at the end of the array and checking if it is smaller than the value. It then moves from right to left until it is not smaller and returns the index. Is there a built in method or a cleaner way to do this?

For example:

var pressureLevels:[CGFloat] = [0, 1.0, 2.133333333333333, 3.266666666666667, 4.4, 5.533333333333334, 6.666666666666667]

var tempPressure: CGFloat = 4.877777

return 4 or return 5

I want to be able to tell that tempPressure is in pressureLevels between 4.4 and 5.533333333333334 and return the index (either 4 or 5).

2
  • Are you looking for a binary search? Then this stackoverflow.com/q/26678362/1187415 might be helpful. Commented Jan 3, 2019 at 17:31
  • Google binary search, i.e. search for an element in an monotonically increasing or decreasing array. Commented Jan 3, 2019 at 17:35

2 Answers 2

1

This will return the higher index, for the next larger value. I have assumed from your example that the array is already sorted

let largerIndex  = pressureLevels.firstIndex(where: { $0 > tempPressure}) 
let smallerIndex = largerIndex - 1

Note the edge cases, if there is no value larger than tempPressure then largerIndex will be nil and if all values in the array are larger then largerIndex will be 0

Sign up to request clarification or add additional context in comments.

1 Comment

largerIndex will be set to pressureLevels.count that's bad design. Don't use magic values to model failures. Use nil instead.
0

Joakim Danielson's way will work fine for sorted arrays. If your array is unsorted you could put the logic in an extension of the Array class like so:

extension Array where Element == CGFloat {
    func huggingIndexes(for value:CGFloat) -> (lower:Int?, upper:Int?) {
        var largestLowerBound:CGFloat?
        var lowerIndex:Int?
        var smallestUpperBound:CGFloat?
        var upperIndex:Int?

        for (index, val) in self.enumerated() {

            if val < value, val >= largestLowerBound ?? val {
                largestLowerBound = val
                lowerIndex = index
            } else if val > value, val <= smallestUpperBound ?? val {
                smallestUpperBound = val
                upperIndex = index
            }

        }

        return (lowerIndex, upperIndex)
    }
}

var pressureLevels:[CGFloat] = [2.133333333333333, 4.4, 6.666666666666667, 1.0, 5.533333333333334, 0.0, 3.266666666666667]

var tempPressure: CGFloat = 4.877777

let huggingIndexes = pressureLevels.huggingIndexes(for: tempPressure)

print(huggingIndexes.lower) //Prints 1
print(huggingIndexes.upper) //Prints 4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.