我想选择具有以下属性的一组子串所覆盖的字符串部分:
例如:
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
然后,我得到每个子字符串的开始和结束位置。我怎么能把它们全部合并,特别是考虑到它们可能重叠并出现在不同的订单中?这甚至是一个好策略吗?
答案 0 :(得分: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