【问题标题】:Cleanest ruby code to split a string with specific rules用特定规则分割字符串的最干净的 ruby​​ 代码
【发布时间】:2011-01-21 15:50:34
【问题描述】:

想象一个这样的数组

[
"A definition 1: this is the definition text",
"A definition 2: this is some other definition text",
"B definition 3: this could be: the definition text"
]

我希望得到以下哈希

hash = {
:A => ["A definition 1", "this is the definition text", "A definition 2", "this is some other definition text"], 
:B => ["B definition 3", "this could be: the definition text"]
}

我正在创建一个词汇表,其中包含字母表中每个字母的哈希值以及定义数组。

我对 Ruby 很陌生,所以我看起来真的很不雅,我在冒号上的行的拆分正则表达式上苦苦挣扎,所以第 3 行只在第一次出现时拆分。

谢谢!

编辑 这是我目前所拥有的

def self.build(lines)
    alphabet = Hash.new()

    lines.each do |line|
      strings = line.split(/:/)
      letter = strings[0][0,1].upcase
      alphabet[letter] = Array.new if alphabet[letter].nil?
      alphabet[letter] << strings[0]
      alphabet[letter] << strings[1..(strings.size-1)].join.strip
    end
    alphabet
  end

【问题讨论】:

  • 要了解如何仅在第一次出现时使用split(),请参阅我的答案,或者更确切地说是查看documentation for split 并查看limit 参数。
  • 呸,谢谢,这个限制参数直到现在我才发现......

标签: ruby regex arrays hash


【解决方案1】:

提供的 raw_definitions 是您的输入:

sorted_defs = Hash.new{|hash, key| hash[key] = Array.new;}

raw_definitions.each do |d|
  d.match(/^([a-zA-Z])(.*?):(.*)$/)
  sorted_defs[$1.upcase]<<$1+$2
  sorted_defs[$1.upcase]<<$3.strip
end

【讨论】:

  • 做得很好,$2 少了 $1,你可以让第二场比赛从头开始吗?
  • 是的,这就是为什么我加了 $1+$2 试试看。这个版本产生了正确的输出,在 IRB 中测试。
【解决方案2】:

只是为了好玩,这里有一个纯功能的替代方案:

defs = [
  "A definition 1: this is the definition text",
  "A definition 2: this is some other definition text",
  "B definition 3: this could be: the definition text"
]

hash = Hash[
  defs.group_by{ |s| s[0].to_sym }.map do |sym,strs|
    [ sym, strs.map{ |s| s[2..-1].split(/\s*:\s*/,2) }.flatten ]
  end
]

require 'pp'
pp hash
#=> {:A=>
#=>   ["definition 1",
#=>    "this is the definition text",
#=>    "definition 2",
#=>    "this is some other definition text"],
#=>  :B=>["definition 3", "this could be: the definition text"]}

还有一个结果相同的非纯功能变体:

hash = defs.group_by{ |s| s[0].to_sym }.tap do |h|
  h.each do |sym,strs|
    h[sym] = strs.map{ |s| s[2..-1].split(/\s*:\s*/,2) }.flatten
  end 
end

请注意,由于使用了s[0].to_sym,这些解决方案仅适用于 Ruby 1.9;要在 1.8.7 中工作,您必须将其更改为 s[0,1].to_sym。要使第一个解决方案在 1.8.6 中工作,您还必须将 Hash[ xxx ] 替换为 Hash[ *xxx.flatten ]

【讨论】:

  • 阅读它时让我头疼,但是 +1 显示了一种非常酷的方式
  • 这是一个有趣的解决方案,它利用了 ruby​​ 语言的细微差别。感谢分享!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 2015-01-06
  • 1970-01-01
  • 2019-11-03
相关资源
最近更新 更多