Reputation: 3836
I have two arrays - grid and pattern
const G = [
[9,9,9,9,9,9]
]
const P = [
[9,9]
]
I want to get every occurrence of P within G. So the output would be something like this:
[
{
line: 0,
charAtStart: 0,
charAtEnd: 2,
},
{
line: 0,
charAtStart: 2,
charAtEnd: 4,
},
{
line: 0,
charAtStart: 4,
charAtEnd: 6,
},
{
line: 0,
charAtStart: 6,
charAtEnd: 8,
},
{
line: 0,
charAtStart: 8,
charAtEnd: 10,
}
]
What I've done so far:
for(let i = 0, l = G.length; i < l; i++) {
if(G[i].toString().includes(P[0].toString())) {
console.log(G[i].toString(), '\n',
P[0].toString(), '\n',
G[i].toString().indexOf(P[0].toString())
)
availableFirstLines.push({
line: i,
charAtStringStart: G[i].toString().indexOf(P[0].toString()),
charAtStringEnd: (G[i].toString().indexOf(P[0].toString())) + P[0].toString().length - 1
})
}
}
So I loop through G
. First of all I check if P
even exists within G[0]
. If so I push its indexOf first char and last char. So my output is
[
{
line: 0,
charAtStart: 0,
charAtEnd: 2,
}
]
problem is that it does detect only first occurrence and then move on. Should I have nested loop to get every occurrence?
Edit I accidentally provided wrong output. I've changed it.
Upvotes: 1
Views: 82
Reputation: 50759
You could recursively do this by using .indexOf()
and passing through a starting index for each new recurse you do. You will need to recurse for each "line" in your graph:
const G = [
[9,9,9,9,9,9]
];
const P = [
[9,9]
];
const findIndexOf = (line, lineArr, innerP, idx = 0) => {
const charAtStart = lineArr.toString().indexOf(innerP.toString(), idx);
const charAtEnd = charAtStart + innerP.toString().length-1;
if(charAtStart === -1)
return [];
return [{line, charAtStart, charAtEnd}, ...findIndexOf(line, lineArr, innerP, charAtEnd)];
}
const res = G.reduce((acc, line, i) =>
[...acc, ...findIndexOf(i, line, P[i])], []);
console.log(res);
If you want the pattern to be batched for every row (not just its associated row in the G
array, you can use an additional inner .reduce()
method, which will loop the pattern over each row in your graph like so:
const G = [
[9,9,9,9,9,9],
[9,9,9,9,9,9]
];
const P = [
[9,9]
];
const findIndexOf = (line, lineArr, innerP, idx = 0) => {
const charAtStart = lineArr.toString().indexOf(innerP.toString(), idx);
const charAtEnd = charAtStart + innerP.toString().length-1;
if(charAtStart === -1)
return [];
return [{line, charAtStart, charAtEnd}, ...findIndexOf(line, lineArr, innerP, charAtEnd)];
}
const res = G.reduce((acc, line, i) =>
[...acc, ...P.reduce((r, p) => [...r, ...findIndexOf(i, line, p)], [])], []);
console.log(res);
Upvotes: 1
Reputation: 527
You only need 1 loop through G, since you said P is going to be a single line array.
Using indexOf
comparing the G value with the pattern will give you the index of the pattern occurrences.
Then you just need to change your indexOf
call to start where the last pattern occurrence ends. The second indexOf parameter will take care of that.
This snippet should work, ignoring ,
characters:
var G = [[9,9,9,9,9,9]];
var P = [[9,9]];
var pattern = P[0].join('');
var availableFirstLines = [];
for (let i = 0; i < G.length; i++) {
var currentArray = G[i];
var stringArray = currentArray.join('');
let indexOccurrence = 0;
while (indexOccurrence != -1) {
// This will set the index to the the beginning of the pattern occurrence.
indexOccurrence = stringArray.indexOf(pattern, indexOccurrence);
if (indexOccurrence != -1) {
availableFirstLines.push({
line: i,
charAtStart: indexOccurrence,
charAtEnd: indexOccurrence + pattern.length
});
// This will make sure to ignore the previous encountered occurrence.
indexOccurrence += pattern.length;
}
}
}
console.log(availableFirstLines);
Upvotes: 0
Reputation: 147186
Basically you need three levels of nested loops:
The third part can be done with a while
loop over indexOf
, setting the fromIndex
value to just past the start of the previous match:
const G = [
[9,9,9,9,9,9]
]
const P = [
[9,9]
]
let availableFirstLines = [];
G.forEach((Gv, Gi) => {
const Gs = Gv.toString();
P.forEach(Pv => {
const Ps = Pv.toString();
let i, fi = 0;
while ((i = Gs.indexOf(Ps, fi)) >= 0) {
availableFirstLines.push({
line: Gi,
charAtStringStart: i,
charAtStringEnd: i + Ps.length - 1
});
fi = i + 1;
}
})
});
console.log(availableFirstLines);
Upvotes: 1