2015-10-22 1 views
2

J'ai un tableau de lettres créé en divisant un mot donné. J'ai un tableau constant des cinq voyelles, et j'utilise cela pour classer chaque lettre dans le tableau de lettres comme une consonne ou une voyelle.Comment regrouper des éléments dans un tableau ruby ​​en fonction des caractéristiques de chaque élément?

VOWELS = ["a","e","i","o","u"] 

letters = "compared".split("") 
    # => ["c", "o", "m", "p", "a", "r", "e", "d"] 

word_structure = letters.map { |letter| VOWELS.include?(letter) ? "v" : "c" } 
    # => ["c", "v", "c", "c", "v", "c", "v", "c"] 

Je veux en quelque sorte réaliser deux choses:

  1. Groupe lettres adjacentes dans le tableau « lettres » qui ont le même « word_structure ».
  2. Reprenez ces groupes et renvoyez chaque combinaison de VCV possible sous la forme d'un autre tableau. V représente un groupement de toutes les voyelles adjacentes, et C représente un groupement de toutes les consonnes adjacentes.

. Dans cet exemple, le premier groupe VCV commence par un "-" car il n'y a pas de premier regroupement de voyelles. Les deux groupes suivants correspondent parfaitement au motif, et le dernier a un autre "-" parce qu'il n'y avait pas de voyelle finale pour compléter le motif.

J'ai expérimenté avec Enumerable # chunk, Enumerable # partition et Enumerable # slice_before, mais ils sont tout simplement confus pour moi. Si quelqu'un comprend un moyen simple d'y parvenir, j'apprécierais vraiment l'aide.

+2

Cela ressemble à un emploi pour les expressions régulières. –

+0

@CarySwoveland J'ai modifié pour le rendre plus clair. – elersong

Répondre

4

Vous pouvez le faire avec une expression régulière (suivi d'un peu brouillon pour insérer des traits d'union au besoin):

VOWELS = 'aeiou' 

R =/
    (?=    # begin positive look-ahead 
     (    # begin capture group 1 
     (?:   # begin a non-capture group 
      [#{VOWELS}]+ # match one or more vowels 
      |   # or 
      \A   # match the beginning of the string 
     )    # end non-capture group 
     [^#{VOWELS}]+ # match one or more consonants 
     (?:   # begin a non-capture group 
      [#{VOWELS}]+ # match one or more vowels 
      |   # or 
      \z   # match end of string 
     )    # end non-capture group 
    )    # end capture group 1 
    )     # end positive lookahead 
    /x     # extended mode 

def extract(str) 
    arr = str.scan(R).flatten 
    arr[0].insert(0, '-') unless VOWELS.include?(arr[0][0]) 
    arr[-1] << '-' unless VOWELS.include?(arr[-1][-1]) 
    arr 
end 

extract 'compare' #=> ["-co", "ompa", "are"] 
extract 'compared' #=> ["-co", "ompa", "are", "ed-"] 
extract 'avacados' #=> ["ava", "aca", "ado", "os-"] 
extract 'zzz'  #=> ["-zzz-"] 
extract 'compaaared' #=> ["-co", "ompaaa", "aaare", "aare", "are", "ed-"] 
+0

Comment puis-je le mettre à jour pour qu'il attrape le dernier groupe si le mot a été changé en "comparé"? Le dernier groupe devrait être "ed-" – elersong

+0

Je suis désolé de ne pas simplement utiliser "comparé" comme mon mot d'exemple. Cela aurait pu être plus clair. – elersong

+0

Je l'ai changé pour faire face à une voyelle manquante à la fin aussi. –

1
"compare" 
.split(/([aeiou]+)/).unshift("-").each_cons(3) 
.each_slice(2).map{|(v1, c, v2), _| v2 ||= "-"; [v1, c, v2].join} 
+0

C'est génial. Mais la même raison pour laquelle certains groupes sont au format -CV entraînerait le format VC-in (si un mot se termine par une consonne). Pouvez-vous expliquer cette réponse afin que je puisse essayer de la modifier pour utiliser également la contrainte de format VC? – elersong

+0

@sawa ça casse à cause de 'v2 = "-"' Existe-t-il une autre façon d'écrire cela? Je ne comprends pas assez pour l'éditer moi-même – elersong

+0

Vous pouvez suivre les lignes que j'ai éditées. – sawa