1
votes

Tous les autres tableaux de nombres impairs dans Swift

J'ai une fonction intitulée "impair" qui renvoie un tableau de nombres impairs uniquement dans une plage inclusive. Il est donné ci-dessous.

func alternatingOdd(from start: Int, to end: Int) -> [Int] {
    var list = odd(from: start, to: end)
    // ... black magic trickery turns removes every other number from list... 
    return list
}

J'essaie de créer une fonction qui renvoie un tableau de tous les autres nombres impairs, au lieu de tous les nombres impairs. Cette fonction doit également être inclusive.

func odd(from start: Int, to end: Int) -> [Int] {
    let list = [Int](stride(from: start, to: end+1, by: 2))
    return list
}

Appeler cette fonction comme ceci: alternatingOdd (from: 1, to: 25) renverrait un tableau de [1, 5 , 9, 13, 17, 21, 25] .

En substance, je demande: comment supprimer proprement tous les autres éléments d'un tableau?

EDIT : la fonction "impair" ne renvoie pas toujours un tableau impair basé sur l'entrée de l'utilisateur. Il renvoie uniquement un tableau de valeurs incrémentées de 2 dans une plage.

Comment puis-je le protéger contre les balles et m'assurer qu'il ne renvoie toujours que des nombres impairs? Autrement dit, chaque élément du tableau ne doit pas être divisible par deux de manière égale.


4 commentaires

que voulez-vous dire "renvoie un tableau de tous les autres nombres impairs"


Sans rapport mais à la place to: end + 1 , vous pouvez écrire through: end


Vous pouvez simplement utiliser le code de la fonction impair , et remplacer par: 2 par par: 4 .


@MohmmadS Il est peut-être plus facile de montrer un exemple. Un tableau de chaque nombre impair de 1 à 9 serait [1, 3, 5, 7, 9] , mais un tableau de chaque autre nombre impair de 1 à 9 serait [1 , 5, 9] , où 3 et 7 sont supprimés.


3 Réponses :


3
votes

Plutôt que de créer les tableaux avec stride filter le truc avec l'opérateur modulo

La fonction impair conserve les nombres impairs p>

func alternatingOdd(from start: Int, to end: Int) -> [Int] {
    let list = odd(from: start, to: end)
    return list.indices.compactMap{$0 % 2 == 0 ? list[$0] : nil }
}

La fonction alternatingOdd utilise compactMap pour filtrer les indices

func odd(from start: Int, to end: Int) -> [Int] {
    return (start...end).filter{$0 % 2 == 1}
}

p>


4 commentaires

êtes-vous sûr que l'indice (de: s'exécute en temps constant? ... ce n'est pas ... nous pouvons facilement trouver une solution O (n) pour la fonction alternatingOdd


les fonctions d'ordre supérieur sont fantaisistes mais nous pouvons le faire en O (n) en échangeant un peu plus d'espace et en utilisant un ancien style de boucle for. avec la condition d'index% 2.


@Naresh j'ai mis à jour la réponse avec une solution plus efficace


wow c'est génial ... c'est beaucoup mieux que la précédente ... pourquoi ne pas changer la dernière ligne en "return stride (from: 0, through: list.count-1, by: 2) .map {list [$ 0 ]} "cela prend 1/3 de la solution actuelle :)



3
votes

Vous pouvez supprimer efficacement chaque deuxième élément d'un tableau (arbitraire) en mappant chaque deuxième tableau index au tableau correspondant element:

func alternatingOdd(from start: Int, to end: Int) -> [Int] {
    let odds = odd(from: start, to: end)
    return everySecond(of: odds)
}

Exemples:

print(everySecond(of: [1, 3, 2, 6, 4, 6])) // [1, 2, 4]
print(everySecond(of: ["H", "E", "L", "L", "O"])) // ["H", "L", "O"]

Vous pouvez maintenant l'utiliser dans votre fonction comme

func everySecond<T>(of array: [T]) -> [T] {
    return stride(from: array.startIndex, to: array.endIndex, by: 2).map { array[$0] }
}


0 commentaires

1
votes

Vous pouvez obtenir tous les autres nombres impairs en une seule fois, et plus efficacement, de cette façon:

func alternatingOdd(from start: Int, to end: Int, every step: Int) -> [Int] {
    guard step > 0  else { return [] }

    let oddStart = max((start % 2 == 0 ? 1 : 0) + start, 1)

    return Array(stride(from: oddStart, through: end, by: 2 * step))
}

alternatingOdd(from: -3, to: 10, every: 2)  //[1, 5, 9]
alternatingOdd(from: -3, to: 25, every: 4)  //[1, 9, 17, 25]

Vous pouvez même changer le nombre de nombres impairs que vous supprimez:

func alternatingOdd(from start: Int, to end: Int, every step: Int) -> [Int] {
    guard start >= 0, step > 0  else { return [] }

    let oddStart = (start % 2 == 0 ? 1 : 0) + start

    return Array(stride(from: oddStart, through: end, by: 2 * step))
}

alternatingOdd(from: 1, to: 25, every: 2)  //[1, 5, 9, 13, 17, 21, 25]
alternatingOdd(from: 1, to: 25, every: 3)  //[1, 7, 13, 19, 25]

Pour les plages qui commencent par un nombre négatif, vous pouvez renvoyer uniquement les nombres impairs positifs, le cas échéant, de cette façon:

func alternatingOdd(from start: Int, to end: Int) -> [Int] {
    guard start >= 0  else { return [] }

    let oddStart = (start % 2 == 0 ? 1 : 0) + start

    return Array(stride(from: oddStart, through: end, by: 4))
}

alternatingOdd(from: 1, to: 25)  //[1, 5, 9, 13, 17, 21, 25]

p >


2 commentaires

Pourquoi le traitement spécial des frontières négatives? Je m'attendrais à ce que alternatingOdd (de: -7, à: 3) renvoie simplement [-7, -3, 1]


@MartinR Je ne pensais pas que des nombres négatifs seraient voulus ici. Mais vous avez raison, selon leur définition, des nombres négatifs pourraient être inclus.