如何删除数组中两个标记元素之间的任何项目?

时间:2016-03-17 17:33:36

标签: arrays ruby

我正试图找到一种方法来删除数组中任何属于两个“标记”的元素,但有一些怪癖。为了给出一个正确的规范,我正在制作的函数应该这样做:

  

S之后删除最早的开始标记 E中的所有元素到最早的结束标记 S,或者最终元素,如果没有。重复此操作,直到没有S为止。删除所有剩余的E

例如,如果我有一个包含以下内容的数组:

这是我目前的代码:

# if the starting token is `1` and the ending one is `2`:
while clearing.include? 1
    from = clearing.index(1)
    to = clearing[from..-1].index(2) + from
    clearing.slice!(from..to)
end
clearing.delete(2)

clearing设置为:

时运行
["a", "b", "c", "d", "e", "f", 1, "g", "h", "i", "j", 1, "k", 2, "l", 2, 2, "m", "n", "o", "p", "q", "r", "s", 1, "t", "u", "v", "w", "x", 1, "y", "z"]

正确退货

["a", "b", "c", "d", "e", "f", "l", "m", "n", "o", "p", "q", "r", "s"]

Online test

它有效,但它很难看,而且我很确定这是一种更惯用的方法。我找不到它,或者想到它,所以我在这里问:我的代码是唯一(理智)做我正在尝试的方式吗?

不幸的是,这是the XY problem的严重情况 - 我正在尝试完成的具体任务是从字符串中删除注释。如果我有输入字符串,我可以使用一个相当简单的正则表达式(/#.*?$/m),但因为它是一个类赋值,我必须从以#开头到:newline的任何内容中删除令牌中的一个令牌。请不要暗示“这很奇怪,为什么不尝试以不同的方式解决整体问题” - 我知道这很奇怪。我希望我能。

2 个答案:

答案 0 :(得分:1)

总的来说,我认为任何解决方案都会像你的一样优雅。我唯一能想到的是你可以通过迭代每个角色一次来加快速度:

i = 0
loop do
  break if i >= clearing.length
  break if clearing[i] == 1
  i += 1
end

loop do
  break if i >= clearing.length
  val = clearing.delete(i)
  break if val == 2
end

这绝对是优雅。

答案 1 :(得分:1)

可以在这里使用Ruby相当模糊的"flip-flop"运算符。我不是建议使用它,只是说'。

clearing.reject { |e| (e==1..e==2) ? true : false }.reject { |e| e==2 }
  #=> ["a", "b", "c", "d", "e", "f", "l", "m", "n", "o", "p", "q", "r", "s"]

第一个块返回false,直到检测到1。然后,它会为true返回1并继续返回true,直到检测到2。它会为true返回2,但会返回false,直到检测到下一个(如果有)1,依此类推。因此,名称“触发器”。通常为触发器操作符给出的示例是读取用开始/结束标记分隔的文件的部分。

似乎(e==1..e==2) ? true : false可以简化为(e==1..e==2),但事实并非如此,因为后一种表达被视为正常范围。人字拖必须有条件形式。

如果要更改reject,请将reject!替换为clearing