Swift: Check Which Value in Nsarray Is Closest to Another Given Value

Swift: Check which value in NSArray is closest to another given value

Save the minimumDifference as a variable.

Then iterate the array. Each time compare the difference in the value from the array to the minimum difference.

If the new difference is smaller then swap out the minimu difference.

At the end of the array you will have the minimum difference.

This is the same as finding the highest value, smallest value, etc...

how to find/filter the array element with the smallest positive difference

In Swift 2 you can do it as a "one-liner" with functional-style
programming:

let numbers = [ 1, 3, 7, 11]
let x = 6

let closest = numbers.enumerate().minElement( { abs($0.1 - x) < abs($1.1 - x)} )!

print(closest.element) // 7 = the closest element
print(closest.index) // 2 = index of the closest element

enumerate() iterates over all array elements together with the
corresponding index, and minElement() returns the "smallest"
(index, element) pair with respect to the closure.
The closure compares the absolute values of the difference of
two elements to x.

(It is assumed here that the array is not empty, so that minElement()
does not return nil.)

Note that this is probably not the fastest solution for large arrays,
because the absolute differences are computed twice for (almost) all
array elements. But for small arrays this should not matter.

Swift 3:

let numbers = [ 1, 3, 7, 11]
let x = 6
let closest = numbers.enumerated().min( by: { abs($0.1 - x) < abs($1.1 - x) } )!
print(closest.element) // 7
print(closest.offset) // 2

The Swift 1.2 version can be found in the edit history.

Find closest item in array that matches criteria in Swift?

Optimised solution using higher order functions:

 func closestMatch(values: [Int64], inputValue: Int64) -> Int64? {
return (values.reduce(values[0]) { abs($0-inputValue) < abs($1-inputValue) ? $0 : $1 })
}

Swift is advancing with every version to optimise the performance and efficiency. With higher order functions finding the closest match in an array of values is much easier with this implementation. Change the type of value as per your need.

Finding the nearest, lower number in a sorted NSArray

The method you are looking for is -[NSArray indexOfObject:inSortedRange:options:usingComparator:]. It performs a binary search. With the options:NSBinarySearchingInsertionIndex option, if the value isn't found exactly, it returns the index where the object would be inserted, which is the index of the least larger element, or the count of items in the array.

NSTimeInterval currentTime = ...;
NSUInteger index = [times indexOfObject:@(currentTime)
inSortedRange:NSMakeRange(0, times.count)
options:NSBinarySearchingInsertionIndex
usingComparator:^(id object0, id object1) {
NSTimeInterval time0 = [object0 doubleValue];
NSTimeInterval time1 = [object1 doubleValue];
if (time0 < time1) return NSOrderedAscending;
else if (time0 > time1) return NSOrderedDescending;
else return NSOrderedSame;
}];
// If currentTime was not found exactly, then index is the next larger element
// or array count..
if (index == times.count || [times[index] doubleValue] > currentTime) {
--index;
}

Check if the values in an array go below a specific value

If it is not an array with lots of data, I don't see the reason why wouldn't you do it like this:

   for (NSNumber *number in myArray) {
if ([number floatValue] < 10.0) {
// alert user
}
}

How to check if an element is in an array

Swift 2, 3, 4, 5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}

contains() is a protocol extension method of SequenceType (for sequences of Equatable elements) and not a global method as in
earlier releases.

Remarks:

  • This contains() method requires that the sequence elements
    adopt the Equatable protocol, compare e.g. Andrews's answer.
  • If the sequence elements are instances of a NSObject subclass
    then you have to override isEqual:, see NSObject subclass in Swift: hash vs hashValue, isEqual vs ==.
  • There is another – more general – contains() method which does not require the elements to be equatable and takes a predicate as an
    argument, see e.g. Shorthand to test if an object exists in an array for Swift?.

Swift older versions:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
println("yes")
}

How to find out which CGRect is closest from array?

You'll need to figure out what Rob asked. One option is signed distance comparison.

Video: Deriving the SDF of a Box

If multiple rectangles contain the point, the "closest" one will be the one whose closest edge to the point is farthest away, i.e. where the point is "more contained".

rects.min { [point = SIMD2(point)] in point.getSignedDistance(to: $0) }
public extension CGRect {
var center: CGPoint { .init(x: midX, y: midY) }
}
public protocol CGFloat2 {
var x: CGFloat { get }
var y: CGFloat { get }
}

extension CGPoint: CGFloat2 { }

extension CGSize: CGFloat2 {
public var x: CGFloat { width }
public var y: CGFloat { height }
}
import simd

public extension SIMD2 where Scalar == CGFloat.NativeType {
init<Float2: CGFloat2>(_ float2: Float2) {
self.init(x: float2.x, y: float2.y)
}

init(x: CGFloat, y: CGFloat) {
self.init(x: x.native, y: y.native)
}

/// Distance to the closest point on the rectangle's boundary.
/// - Note: Negative if inside the rectangle.
func getSignedDistance(to rect: CGRect) -> Scalar {
let distances =
abs( self - Self(rect.center) )
- Self(rect.size) / 2
return
all(sign(distances) .> 0)
? length(distances)
: distances.max()
}
}
public extension Sequence {
func min<Comparable: Swift.Comparable>(
by getComparable: (Element) throws -> Comparable
) rethrows -> Element? {
try self.min {
try getComparable($0) < getComparable($1)
}
}
}

Swift: Checking JSON values stored in values of NSMutableArray

  • Get the ID from the JSON entry in the question

Any reason you need to have the ID thing in Int?
If no, keep your questionID as a String.

let questionID = entry["id"] as! String

(If yes, you can do something like this, but I omit this case.)

        let questionID = Int(entry["id"] as! String)!

(Assuming your "content.json" never contains unexpected values...)

  • store that in an array called alreadyAsked

Declare an instance property as:

    var alreadyAsked: Set<String> = []

And append the questionID as :

        alreadyAsked.insert(questionID)

(I hope you know where you need to put this line.)

  • check if the question that is loaded has already been seen. If so, skip and choose another

You can check it here and there in your code, but one possible place is inside the LoadQuestion(_:) method.

You may need to return a value which indicates that the question is already asked:

    func loadQuestion(index : Int) -> Bool

(You'd better follow a simple naming guideline: Use upper camel case only for types. Which improves the readability of your code when shared. I mean "shared" includes posting a question in a Q&A site.)

And after you get that questionID, check it:

        if alreadyAsked.contains(questionID) {
return false //already asked, so not again
}

You need to put return true at the end of loadQuestion(_:).

You may need to repeat until loadQuestion(_:) returns true.

        var randomNumber: Int
repeat {
randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
} while !loadQuestion(randomNumber)

(This is not efficient, but practically ("seemingly" would fit better?) it works. And keeping your word "If so, skip and choose another")

  • if all questions have been seen, display in console none left to view

Check it before entering the loop above:

        if allEntries.count > alreadyAsked.count {
var randomNumber: Int
repeat {
randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
} while !loadQuestion(randomNumber)
loadScore()

adjustInterface()
} else {
//display in console none left to view
//...
}

Your code has many parts which are unsafe or in a bad manner, and some of them may be critical. You may post another question if you cannot resolve it yourself.



Related Topics



Leave a reply



Submit