2017-10-20 9 views
-1

Ceci est une question de l'académie de l'application des questions de préparation - quelqu'un pourrait-il expliquer la réponse. Je ne comprends pas comment l'ordre des opérations dans ce travail boucle while:Quel est l'ordre des opérations dans Ruby?

def dasherize_number(num) 
    i = 0 
    dashed = "" 
    num_s = num.to_s 

    while i < num_s.length 
    digit = num_s[i].to_i 
    if i > 0 
     prev_digit = num_s[i-1].to_i 
     if prev_digit%2 == 1 || digit%2 == 1 
     dashed += "-" ## THIS LINE COMES FIRST 

     end 
    end 

    dashed += num_s[i] ## WHY IS THIS ADDED TO "DASHED" FIRST? 

    i += 1 
    end 
    return dashed 
end 

puts(dasherize_number(32467743)) 

le résultat est 3-245-7-7-4-3 de sorte que tous les nombres impairs ont un tableau de bord de chaque côté, sauf les cas finaux.

Cela n'a aucun sens pour moi que la commande pour insérer un tiret est ajoutée à la nouvelle chaîne après la lettre d'origine même si elle vient en premier dans le code.

Merci!

+0

Voulez-vous dire [priorité de l'opérateur] (https: // ruby- doc.org/core-2.2.0/doc/syntax/precedence_rdoc.html)? Vous devriez probablement parcourir ce code et mieux le déboguer, en affichant les résultats de chaque itération. – tadman

+0

Indice: 'digit.odd?' Pourrait être plus explicite que l'astuce modulo. – tadman

Répondre

0

Dans la première itération du bloc de tout cette condition n'est pas vrai

if i > 0 

Mais le chiffre est ajouté à dashed et de la prochaine itération même la condition est vraie et ces deux choses ensemble sont probablement source de confusion

+0

Ah d'accord, j'ai compris. Merci! –

0

suivons les deux premières itérations du code while.

i = 0 num_s = "32467743"

l'intérieur de la boucle while.

  • digit = 3, i = 0, if i > 0 is false, SO dashed = "3"
  • digit = 2, i = 1, prev_digit = 3, if i > 0 is true, if prev_digit%2 == 1 || digit%2 == 1 is true, SO dashed = "3-", alors le bloc de sortie de code if i > 0, puis pointillée est mis à jour dashed = 3-2

tout fonctionne d'accord et dans l'ordre.

0

Voici quelques solutions alternatives à des fins éducatives. Celui-ci utilise odd? et flat_map pour compiler un tableau de pièces de caractère, puis compacte ensemble et bandes à paillettes indésirables:

def dasherize_number(num) 
    num.to_s.chars.map(&:to_i).flat_map do |d| 
    if (d.odd?) 
     [ '-', d, '-' ] 
    else 
     d 
    end 
    end.join('').gsub(/\-\-+/, '-').sub(/\A\-/, '').sub(/\-\z/, '') 
end 

Voici un qui fonctionne sur un niveau d'expression régulière en appliquant plusieurs substitutions dans une rangée pour obtenir la résultat final:

def dasherize_number(num) 
    { 
    /([13579])/ => '-\1-', 
    /\-\-+/ => '-', 
    /\A\-/ => '', 
    /\-\z/ => '' 
    }.inject(num.to_s) do |n, (rx, sub)| 
    n.gsub(rx,sub) 
    end 
end 
0

Ajouter puts pour tracer ce qui se passe:

def dasherize_number(num) 
    i = 0 
    dashed = "" 
    num_s = num.to_s 
    puts "number=#{num_s}" 

    while i < num_s.length 
    digit = num_s[i].to_i 
    if i > 0 
     prev_digit = num_s[i-1].to_i 
     puts "prev_digit=#{prev_digit} digit=#{digit}" 

     if prev_digit%2 == 1 || digit%2 == 1 
     dashed += "-" ## THIS LINE COMES FIRST 
     puts "dashed in if=#{dashed}" 
     end 
    end 

    dashed += num_s[i] ## WHY IS THIS ADDED TO "DASHED" FIRST? 
    puts "dashed + num=#{dashed}" 

    i += 1 
    end 
    return dashed 
end 

puts(dasherize_number(32467743)) 

exécution:

$ ruby -w t.rb 
number=32467743 
dashed + num=3 
prev_digit=3 digit=2 
dashed in if=3- 
dashed + num=3-2 
prev_digit=2 digit=4 
dashed + num=3-24 
prev_digit=4 digit=6 
dashed + num=3-246 
prev_digit=6 digit=7 
dashed in if=3-246- 
dashed + num=3-246-7 
prev_digit=7 digit=7 
dashed in if=3-246-7- 
dashed + num=3-246-7-7 
prev_digit=7 digit=4 
dashed in if=3-246-7-7- 
dashed + num=3-246-7-7-4 
prev_digit=4 digit=3 
dashed in if=3-246-7-7-4- 
dashed + num=3-246-7-7-4-3 
3-246-7-7-4-3 

pointillées + = num_s [i] ## Pourquoi est-ce ajouté à "POINTILLÉE" PREMIER?

La boucle commence par i = 0, de sorte que if i > 0 n'est pas exécuté.

+ = DASHED « - » ## CETTE LIGNE EST UNE PRIORITE

Oui, d'abord dans les lignes, mais pas en cours d'exécution, précisément parce qu'il est dans le bloc then selon la if i > 0, qui n'est pas exécuté lors de la première itération, permettant à dashed += num_s[i] d'ajouter le premier nombre à la chaîne dashed vide.

dashed + num=3 

Il est seulement dans la deuxième itération i = 1, de sorte que if i > 0 devient vrai et permet dashed += "-" à exécuter:

dashed in if=3-