Notez tout d'abord que votre approche de la "valeur initiale" et du "cast" forcé n'a rien à voir avec l'approche de la "valeur initiale". forcée
var max = 0 as! T
a deux problèmes :
- Il se plantera pour les tableaux ne contenant pas d'entiers, par exemple
max(["a", "b"]
).
- Même pour les tableaux d'entiers, c'est une erreur si tous les éléments du tableau sont des négatifs, par exemple
max([-2, -3])
devrait être -2
et non zéro.
Il est donc préférable de choisir le premier élément du tableau comme valeur initiale plutôt que le "zéro forcé".
Cela nous amène à la question suivante : Que se passe-t-il si le tableau est vide ? Il existe deux approches valables : Vous pouvez exiger que le fonction soit appelée avec un tableau non vide (et documenter cette cette condition préalable) :
/// Compute the maximal element in an array.
///
/// - Returns: The maximal element.
///
/// - Note: The array must not be empty.
func max<T: Comparable>(_ array: [T]) -> T {
precondition(!array.isEmpty, "`max` called with empty array")
var max = array[0]
for value in array {
if value > max { max = value }
}
return max
}
Ou bien (comme suggéré dans les autres réponses) faire en sorte que la valeur de retour soit optionnelle :
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
guard var max = array.first else { return nil }
for value in array {
if value > max { max = value }
}
return max
}
Les deux approches peuvent être mises en œuvre avec reduce()
. Le premier serait
/// Compute the maximal element in an array.
///
/// - Returns: The maximal element.
///
/// - Note: The array must not be empty.
func max<T: Comparable>(_ array: [T]) -> T {
precondition(!array.isEmpty, "`max` called with empty array")
return array.reduce(array[0]) { $0 > $1 ? $0 : $1 }
}
et le second
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
guard let first = array.first else { return nil }
return array.reduce(first) { $0 > $1 ? $0 : $1 }
}
Il est possible de raccourcir encore ce délai à l'aide de la fonction flatMap()
méthode de Optional
:
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
return array.first.flatMap { array.reduce($0) { $0 > $1 ? $0 : $1 } }
}
Enfin, vous pouvez utiliser l'outil existant
func max<T : Comparable>(_ x: T, _ y: T) -> T
au lieu d'une fermeture littérale dans tous les exemples ci-dessus, par exemple
/// Compute the maximal element in an array.
///
/// - Returns: `nil` if the array is empty, and the maximal element otherwise.
func max<T: Comparable>(_ array: [T]) -> T? {
return array.first.flatMap { array.reduce($0, max) }
}