2
\$\begingroup\$

I need a function which finds the left and right neighbor-element within an integer-array, based upon a given index. If the given element is 0, then it shall return largest index as left neighbor. When the given index is the largest index, then it shall return 0 as right neighbor.

Here's the solution, I have created:

// ------- Actual function ----------------------
func findNeighborsWithin(array: [Int], viewingElement index: Int) -> [Int] {
 var neighbors = [Int]()
 if index > 0 {
 neighbors.append(index - 1)
 } else {
 neighbors.append(array.count - 1)
 }
 if index < array.count - 1 {
 neighbors.append(index + 1)
 } else {
 neighbors.append(0)
 }
 return neighbors
}
// ------------------------------------------------
// Testing/Example-usage
let array = [0, 1, 2, 4, 8, 16, 32, 64]
print("Index 0 -> \(findNeighborsWithin(array: array, viewingElement: 0))")
print("Index \(array.count - 1) -> \(findNeighborsWithin(array: array, viewingElement: array.count - 1))")
for i in 0..<5 {
 let randInt = Int.random(in: 0..<array.count)
 print("Index \(randInt) -> \(findNeighborsWithin(array: array, viewingElement: randInt))")
}
/*
 Index 0 -> [7, 1]
 Index 7 -> [6, 0]
 Index 4 -> [3, 5]
 Index 6 -> [5, 7]
 Index 3 -> [2, 4]
 Index 5 -> [4, 6]
 Index 6 -> [5, 7]
 */

What's are your thoughts on my solution, including naming and formatting? Is there a better solution? How can it become improved? What would you have done differently and why?

Martin R
24.2k2 gold badges37 silver badges95 bronze badges
asked Aug 3 at 9:17
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Some notes:

  • The contents and the element type of the array is irrelevant to the outcome of the function, only the array count is needed. Therefore I would pass that count as an argument instead of an entire array.

  • The function always returns a pair of indices, therefore I would use a two-element (named) tuple as the return type instead of an array.

  • The function returns something even if the passed index it invalid for the given array. I suggest to test the parameters with a precondition.

  • The conditional operator ?: can be used to compute the left and right indices instead of if statements.

  • In the spirit of the Swift Naming Guidelines I would call the function something like neighboringIndices(for:inArrayOfLength:)

Putting it together, I suggest the following implementation:

func neighboringIndices(for index: Int, inArrayOfLength count:Int) -> (left: Int, right: Int) {
 precondition(index >= 0 && index < count, "Invalid index")
 let leftNeighbor = index == 0 ? count - 1 : index - 1
 let rightNeighbor = index == count - 1 ? 0 : index + 1
 return (leftNeighbor, rightNeighbor)
}

Alternatively, with a "branchless" computation:

 let leftNeighbor = (index - 1 + count) % count
 let rightNeighbor = (index + 1) % count

Testing/example usage:

let array = [0, 1, 2, 4, 8, 16, 32, 64]
print(neighboringIndices(for: 0, inArrayOfLength: array.count)) // (7, 1)
print(neighboringIndices(for: 3, inArrayOfLength: array.count)) // (2, 4)
print(neighboringIndices(for: array.count - 1, inArrayOfLength: array.count)) // (6, 0)
// Access return value via named tuple accessors:
let neighbors = neighboringIndices(for: 5, inArrayOfLength: array.count)
print(neighbors.left) // 4
print(neighbors.right) // 6
// Invalid index:
print(neighboringIndices(for: 999, inArrayOfLength: array.count))
// Precondition failed: Invalid index

In addition I suggest to add unit tests.

answered Aug 3 at 11:21
\$\endgroup\$
1
  • \$\begingroup\$ The % count branchless solution is the shortest and most beautiful solution \$\endgroup\$ Commented Aug 3 at 20:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.