0

I have an array of SCNNode that are sorted by their y positions(Float):

nodesSortedByY = scene.rootNode.childNodes.sorted { $0.position.y > $1.position.y }

What I would like to do is get a new array from nodesSortedByY where the y values are within a certain range in a similar way to how subscript works but by passing actual values not indexes.

For example:

let nodesSortedByY = [5.0, 4.0, 4.0, 3.0, 2.0, 2.0, 1.0]
let subRange = nodesSortedByY(4.0...2.0)
print(subRange) // [4.0, 4.0, 3.0, 2.0, 2.0]

I tried using indexes originally combined with this binary search but it doesnt work if the values dont exist within the array:

let yPositions = nodesSortedByY.map({ $0.position.y })
let firstIndex = yPositions.binarySearch(forFirstIndexOf: firstValue) ?? 0
let lastIndex = yPositions.binarySearch(forLastIndexOf: lastValue) ?? 0
nodesSortedByY[lastIndex...firstIndex]
6
  • Are you looking for filter()? let filtered = nodesSortedByY.filter({ (2.0...4.0).contains($0) }) Commented Oct 22, 2020 at 14:26
  • Not quite, it would have to be filtered by a range of the nodes y positions somehow? Commented Oct 22, 2020 at 14:30
  • DIdn't you want to get all the values of "y" if they are between 2.0 and 4.0? That's what's doing the filter. Else, keeping your last idea: let lowerBound = nodesSortedByY.firstIndex(where: { $0 <= 4.0 }) let upperBound = nodesSortedByY.lastIndex(where: { $0 >= 2.0 }) let sub = nodesSortedByY[lowerBound!...upperBound!] Commented Oct 22, 2020 at 14:33
  • i want an array of SCNNode still but sorting it by y and getting the the new range array by the nodes y values Commented Oct 22, 2020 at 14:36
  • I guess so, but the author used map, and simplified his example to [Double], but my solutions should work. Commented Oct 22, 2020 at 14:37

1 Answer 1

1

What you want is to filter().

let sub = nodesSortedByY.filter { (2.0...4.0).contains($0.position.y) }

We keep only the elements in nodesSortedByY where its y position is inside the range [2.0; 4.0].

Since you sorted your array (descending order), you can applied that logic too (modification of your attempt)

let lowerBound = nodesSortedByY.firstIndex(where: { $0 <= 4.0 }) ?? nodesSortedByY.startIndex
let upperBound = nodesSortedByY.lastIndex(where: { $0 >= 2.0 }) ?? nodesSortedByY.endIndex
let sub = nodesSortedByY[lowerBound...upperBound]
Sign up to request clarification or add additional context in comments.

2 Comments

let sub = nodesSortedByY.filter { (2.0...4.0).contains($0.position.y) } works perfectly for me thank you, i didnt realize you could filter like that
@Wazza 2.0...4.0 ~= $0.position.y

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.