Task:
Write a function which rotates all elements of a given array to the right.
Example: [1, 2, 3] => [3, 1, 2]
My solution:
func rotateRight(array ary: [Int]) -> [Int] { guard ary.isEmpty == false else { return ary } var copy = ary let last = ary.last var i = ary.count - 1 while i > 0 { copy[i] = copy[i - 1] i -= 1 } copy[0] = last! return copy}var ary1 = [1, 2, 3]print(rotateRight(array: ary1)) // [3, 1, 2]var ary2 = [1, 1, 2, 3, 3, 4]print(rotateRight(array: ary2)) // [4, 1, 1, 2, 3, 3]var ary3 = [Int]()print(rotateRight(array: ary3)) // []var ary4 = [1]print(rotateRight(array: ary4)) // [1]I have to make a copy of the array because Swift-parameter are immutable.Do I handle the issue in a proper way? Or should it be done differently?
Is there a better way to solve the described task?
- 1\$\begingroup\$
guard let last = ary.last else { return ary }; return [last] + ary.dropLast()\$\endgroup\$ielyamani– ielyamani2024-12-28 18:53:09 +00:00CommentedDec 28, 2024 at 18:53 - 1\$\begingroup\$
return ary.isEmpty ? ary : ary.suffix(1) + ary.prefix(ary.count - 1)\$\endgroup\$ielyamani– ielyamani2024-12-28 18:55:31 +00:00CommentedDec 28, 2024 at 18:55
1 Answer1
A comparison againsttrue orfalse is never needed,ary.isEmpty == false is more concisely expressed as!ary.isEmpty.
Here I would not use aguard statement at all. That statement was introduced to get rid of the “if-let pyramid of doom,” to unwrap a variable without introducing another scope/indentation level. But I would not use aguard statement for every “early return” situation, in particular not if it makes the statement look like a double negation.
if ary.isEmpty { return ary}is shorter and clearer in my opinion. Alternatively one can use optional binding
if let last = ary.last { // ...} else { return ary}to test for a non-empty arrayand get the last element in one step, that allows to get rid of the ugly forced unwrapcopy[0] = last! in your code.
As already mentioned in the comment, arrayslicing methods can be used instead of copying all elements to their new place:
if let last = ary.last { return [last] + ary.dropLast()} else { return ary}Another option is to concatenate two array slices, this can easily be generalized to shifting array elements by more than one position to the right or left:
if ary.isEmpty { return ary}let frontIndex = ary.count - 1return Array(ary[frontIndex...]) + ary[0..<frontIndex]Naming: The parameter nameary reminds my of unary/binary/arity and is not significantly shorter thanarray. My suggestion is to usearray with an empty argument label:
func rotateRight(_ array: [Int]) -> [Int] { // ... }var array1 = [1, 2, 3]print(rotateRight(array1)) // [3, 1, 2]Of course, if you don't want to reinvent the wheel then you can simply use therotate(toStartAt:) method of theswift-algorithms package.
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.

