【问题标题】:Select string covered by different substrings选择不同子字符串覆盖的字符串
【发布时间】:2014-03-12 07:28:59
【问题描述】:

我想选择具有以下属性的一组子字符串覆盖的字符串部分:

  • 它们属于原始字符串。
  • 它们可能有不同的长度和位置。
  • 它们可以重叠。
  • 它们可能不会按照它们在原始字符串中出现的顺序排列。

例如:

string = "MGLSDGEWQQVLNVWGKVEADIAGHGQEVLIHSKHPGDFGADAQGAMTKALELFRNDIAAKYKELGFQG"
substring1 = "HPGDFGADAQGAMTKALELFR"
substring2 = "GEWQQVLNVWGK"
substringn = "ALELFRNDIAAKYK"

我想得到:

coverage = "MGLSD<b>GEWQQVLNVWGK</b>VEADIAGHGQEVLIHSK<b>HPGDFGADAQGAMTKALELFRNDIAAKYK</b>ELGFQG"

我试图提取字符串中子字符串的位置,如下所示:

substrings_array.each do |substring|
  start_pos = string.index substring
  end_pos = string.length - (string.reverse.index(substring.reverse) )
end

这样,我得到每个子字符串的开始和结束位置。我怎样才能将它们全部合并,特别是考虑到它们可能重叠并以不同的顺序出现?这甚至是一个好策略吗?

【问题讨论】:

  • 这看起来是一个不错的开始策略,尤其是如果你将.each 转换为.map 并返回需要标记的开始/结束位置列表。然后你的问题就变成了“我如何合并这些范围,以便重叠的范围合并成一个更大的范围”。
  • 我会说你已经完成了 80%,所以你想做的是在 start_pos 插入 &lt;b&gt; 和在 end_pos 插入 &lt;\b&gt;,这似乎已经完成了,你可以 clone字符串并修改克隆的字符串,然后返回克隆的字符串作为您的答案,例如new_string = string,然后在获得start_posend_pos 之后,您想在new_string 中插入标签,用于插入的ruby 文档是@ 987654321@

标签: ruby string substring


【解决方案1】:

这应该有效(不漂亮,但有效):

string = "MGLSDGEWQQVLNVWGKVEADIAGHGQEVLIHSKHPGDFGADAQGAMTKALELFRNDIAAKYKELGFQG"
substring1 = "HPGDFGADAQGAMTKALELFR"
substring2 = "GEWQQVLNVWGK"
substring3 = "ALELFRNDIAAKYK"

substrings = [substring1, substring2, substring3]

overlapping_indexes = substrings.map do |substring|
  start_pos = string.index substring
  end_pos = start_pos + substring.length
  (start_pos..end_pos)
end

# the following 3 methods are from Wayne Conrad in this question: http://stackoverflow.com/questions/6017523/how-to-combine-overlapping-time-ranges-time-ranges-union

def ranges_overlap?(a, b)
  a.include?(b.begin) || b.include?(a.begin)
end

def merge_ranges(a, b)
  [a.begin, b.begin].min..[a.end, b.end].max
end

def merge_overlapping_ranges(ranges)
  ranges.sort_by(&:begin).inject([]) do |ranges, range|
    if !ranges.empty? && ranges_overlap?(ranges.last, range)
      ranges[0...-1] + [merge_ranges(ranges.last, range)]
    else
      ranges + [range]
    end
  end
end

indexes = merge_overlapping_ranges(overlapping_indexes)

x = "<b>"
y = "</b>"
offset = 0

indexes.each do |index|
  string.insert(index.begin + offset, x)
  offset += x.length
  string.insert(index.end + offset, y)
  offset += y.length
end

p string

【讨论】:

  • 这行不通。插入的标签将破坏原始字符串,避免与与当前子字符串重叠的另一个子字符串进一步匹配。
  • @sawa - 你是对的。我更新了我的答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多