【问题标题】:How can I group items in a ruby array based on characteristics of each element?如何根据每个元素的特征对 ruby​​ 数组中的项目进行分组?
【发布时间】:2016-01-21 08:32:13
【问题描述】:

我有一个通过拆分任何给定单词创建的字母数组。我有一个包含所有五个元音的常量数组,我用它来将字母数组中的每个字母分类为辅音或元音。

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"]

我想以某种方式实现两件事:

  1. 将“letters”数组中具有相同“word_structure”的相邻字母分组。
  2. 获取这些组并将每个可能的 VCV 组合作为另一个数组返回。 V代表所有相邻元音的分组,C代表所有相邻辅音的分组。

.

 groups = ["c", "o", "mp", "a", "r", "e", "d"]

 vcv_groups = ["-co", "ompa", "are", "ed-"]

在本例中,第一个 VCV 组以“-”开头,因为没有第一组元音。接下来的两组完全符合模式,最后一组有另一个“-”,因为没有最后的元音来完成模式。

我已经尝试过 Enumerable#chunk、Enumerable#partition 和 Enumerable#slice_before,但它们都让我感到困惑。如果有人了解实现此目的的简单方法,我将非常感谢您的帮助。

【问题讨论】:

  • 这看起来像是正则表达式的工作。
  • @CarySwoveland 我已对其进行了编辑以使其更清晰。

标签: arrays ruby enumerable


【解决方案1】:

您可以使用正则表达式来做到这一点(后跟一个杂乱的位以根据需要插入连字符):

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-"]

【讨论】:

  • 如何更新它以便在单词更改为“比较”时捕获最后一组?最后一组应该是“ed-”
  • 我很抱歉没有使用“比较”作为我的示例词。本来可以更清楚的。
  • 我将其更改为处理末尾缺少的元音。
  • 我已经接受它作为最佳答案。非常感谢@caryswoveland。我只需要弄清楚如何在领先组的开头获得破折号,在尾随组的末尾获得破折号。
  • 我做了另一个编辑,根据需要在开头和结尾插入连字符。
【解决方案2】:
"compare"
.split(/([aeiou]+)/).unshift("-").each_cons(3)
.each_slice(2).map{|(v1, c, v2), _| v2 ||= "-"; [v1, c, v2].join}

【讨论】:

  • 这太棒了。但同样的原因,某些组的格式为 -CV 会导致其他组的格式为 VC-(如果单词以辅音结尾)。你能解释一下这个答案,以便我可以尝试修改它以使用 VC 格式约束吗?
  • @sawa 它因为 'v2 = "-"' 而崩溃了 有没有另一种写法?我还不够了解,无法自己编辑
猜你喜欢
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多