I need to write a function that is going to take a string and an array of substrings. and I need to add some HTML tag to wrap the substrings in the string. If two such substrings overlap, I should wrap them together with only one pair of tag.
The first thing I need to do is to get the start indices and end indices of where a substring occurs in the string. For example:
const str = 'aabc'
const target = ['aa', 'bc']
I need to be able to know that the indices for the substrings are [[0,2], [2,4]] where the start index is inclusive and the end index is exclusive.
Here is my attempt
function findOccurrances(str, words) {
return words.map((word) => [
str.indexOf(word),
str.indexOf(word) + word.length,
])
}
However, if target is ['a', 'bc'], the result should be [[0, 1], [1,2], [2,4] but since indexOf only returns the first occurrence of the substring, we only get [[0, 1], [2,4] as the result using my function.
I wonder what are some ways to achieve this?
const str = 'aabc'
const target = ['aa', 'bc']
function findOccurances(str, words) {
const list = []
str.split('').forEach((c,i) => {
words.forEach(t => {
if (str.substr(i, t.length) === t) {
list.push([i, i + t.length])
}
})
})
return list
}
console.log(findOccurances(str, target))
You could combine reduce with another recursive inner function and in each call pass remaining word text.
function findOccurrances(str, words) {
const f = (word, rest, last = 0) => {
const result = []
const index = rest.indexOf(word)
if (index != -1) {
result.push([last + index, last + index + word.length])
result.push(...f(word, rest.slice(index + 1), last + index + 1))
}
return result;
}
return words.reduce((r, e) => {
r.push(...f(e, str))
return r;
}, [])
}
console.log(findOccurrances('aabc', ['a', 'bc']))
console.log(findOccurrances('aabc', ['bc', 'aa']))
console.log(findOccurrances('azzz', ['zz']))
Created a String.stringIndex method which takes a substring as parameter , finds the start and end index of substring in the parent string . Finally , returning an array of start and end indexes. Using this method i created a function which you can use to get the results as you expect !
String.prototype.stringIndex = function(t) {
t = Array.from(t);
let start_index = this.indexOf(t[0]);
let end_index = this.slice(start_index + 1, this.length);
if (t.length == 1) {
end_index = start_index;
} else {
let increment = start_index + 1 ;
end_index = end_index.indexOf(t[t.length - 1]) + increment;
}
return [start_index,
end_index];
}
function findOccurrances(string, words) {
return words.map((word) => string.stringIndex(word));
}
console.log(findOccurrances("i love chocolates", ["love", "chocolates"]));