【问题标题】:Ruby Scan with regex not finding all patterns [closed]使用正则表达式进行 Ruby 扫描未找到所有模式 [关闭]
【发布时间】:2014-10-18 04:48:51
【问题描述】:

我正在尝试使用正则表达式来查找 word 中的所有子字符串。它正在寻找一些但不是全部。在这样的例子中,“香蕉”一词中的“an”。

def substrings str
  pattern = '.'
  subs = []    
  while pattern.length < str.length do
    subs << str.scan(/#{pattern}/)
    pattern << '.'  
  end 
  subs.flatten  
end

puts substrings("banana").sort_by{ |s| "banana".index(/#{s}/)}

【问题讨论】:

  • 您的问题是什么?还有,你想做什么?
  • @sawa 我希望它返回传入的单词中的所有子字符串,而不仅仅是一些。
  • 不只是str.scan /#{pattern}/ 没有产生匹配字符串的数组吗?我不明白需要手动推送数组中的每个模式。
  • @AkashAgrawal 我正在推动,因为我从长度为 1 的子字符串开始,一直到字符串长度 -1
  • @CarySwoveland 那是因为在我明白你在问什么之前我就已经列出了清单。

标签: ruby regex substring


【解决方案1】:
def substrings str
  (0...str.length).flat_map{|i| (i...str.length).map{|j| str[i..j]}}.uniq
end

substrings("banana")

结果

[
  "b",
  "ba",
  "ban",
  "bana",
  "banan",
  "banana",
  "a",
  "an",
  "ana",
  "anan",
  "anana",
  "n",
  "na",
  "nan",
  "nana"
]

def substrings str
  (0...str.length).to_a.combination(2).map{|r| str[*r]}.uniq
end

结果

[
  "b",
  "ba",
  "ban",
  "bana",
  "banan",
  "banana",
  "an",
  "ana",
  "anan",
  "anana",
  "nan",
  "nana",
  "na",
  "a"
]

【讨论】:

  • 我之前考虑过这种方法,但我更喜欢使用正则表达式
  • 那就按照自己的方式去吧。
【解决方案2】:

这是另一种不使用正则表达式的方法。我现在看到了如何使用正则表达式来完成它,但我不知道你为什么想要这样做,除非它只是一个练习。

def substrings(str)
  arr = str.chars
  (1..str.size).each_with_object([]) { |i,a|
    a << arr.each_cons(i).to_a.map(&:join) }.flatten
end

substrings("banana")
  #=> ["b", "a", "n", "a", "n", "a", "ba", "an", "na", "an", "na", "ban",
  #    "ana", "nan", "ana", "bana", "anan", "nana", "banan", "anana"]

如果您想包含“香蕉”一词,请将str.size 更改为str.size+1

【讨论】:

  • 不,不是。来自 OP:“香蕉”一词中的“an”也不在您的结果中。
  • @CarySwoveland 我没有对你投反对票
  • 我也没有。而且问题很清楚(除非您看不懂拼写错误):“word 中的所有子字符串”。
【解决方案3】:

正则表达式匹配永远不会重叠。如果你要求/../,你会得到["ba", "na", "na"]。你不会得到["ba", "an" ...],因为"an""ba" 重叠。下一个匹配搜索总是从最后一个匹配的结尾开始。

如果你想找到重叠的序列,你需要使用前瞻/后瞻来缩短匹配大小,这样匹配本身就不会重叠:/(?=(..))/。请注意,您必须引入一个捕获组,因为在这种情况下匹配本身是一个空字符串。

【讨论】:

  • 只匹配固定长度的子串。
  • @sawa:这说明了一个原则,该原则可以应用到 OP 的代码中,只需进行最少的更改。我认为我不需要为您详细说明解决方案,但这里是:subs &lt;&lt; str.scan(/(?=(#{pattern}))/).flatten
  • @sawa:如果我写的话,我宁愿做你所做的,不用正则表达式。但这是修复它的 OP 代码的最小修改,解释了问题的根源,并教导了正则表达式引擎的一个重要属性。
  • 我看到:subs = []; subs &lt;&lt; str.scan(/(?=(...))/).flatten =&gt; [["ban", "ana", "nan", "ana"]],重复不同的长度,最后是subs.flatten。那很好。 @sawa,我想你忘记带一对牙套了:/(?=(.{#{n}}))/
猜你喜欢
  • 2021-05-20
  • 2016-09-28
  • 2013-04-10
  • 2012-01-06
  • 1970-01-01
  • 2016-11-20
  • 2017-02-18
  • 2016-01-23
  • 1970-01-01
相关资源
最近更新 更多