I have a JavaScript array like:
var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'];
I want to fetch only those elements of the array that come after 2 consequent occurrences of a particular element.
ie in the above array, I want to fetch all the elements that come after consequent 'x', 'x'
So my output should be:
'p'
'b'
I have a solution like :
var arrLength = myArray.length;
for (var i = 0; i < arrLength; i++) {
if(i+2 < arrLength && myArray[i] == 'x' && myArray[i+1] == 'x') {
console.log(myArray[i+2]);
}
};
This satisfies my needs, but it is not so generic.
For eg. if I have to check for 3 consequent occurrences, then again I have to add a condition inside if for myArray[i+2] == 'x'
and so on.
Could anyone provide a better way to fetch the elements?
The functional way would be to use recursion. With an ES6 spread, you can pretty much emulate the terseness of a truly 'functional' language :-)
var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'];
function reducer(acc, xs) {
if (xs.length > 2) {
if (xs[0] === xs[1]) {
// add the third element to accumulator
// remove first three elements from xs
// return reducer([xs[2], ...acc], xs.slice(3));
// or per Nina's question below
return reducer([xs[2], ...acc], xs.slice(1));
} else {
// remove first element from xs and recurse
return reducer(acc, xs.slice(1))
}
} else {
return acc;
}
}
console.log(reducer([], myArray));
A generic straight forward approach for any comparable content.
function getParts(array, pattern) { return array.reduce(function (r, a, i) { i >= pattern.length && pattern.every(function (b, j) { return b === array[i + j - pattern.length]; }) && r.push(a); return r; }, []); } function p(o) { document.write('<pre>' + JSON.stringify(o, 0, 4) + '</pre>'); } p(getParts(['a', 'x', 'x', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'], ['x', 'x'])); p(getParts(['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'], ['a', 'x', 'b'])); p(getParts(['a', 'b', 'c', 'd', 'z', 'y', 'a', 'b', 'c', 'd', 'x', 'x'], ['a', 'b', 'c', 'd'])); p(getParts([41, 23, 3, 7, 8, 11, 56, 33, 7, 8, 11, 2, 5], [7, 8, 11]));
You can try following logic
var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; function search(ch, times) { var splitStr = ""; for(var i = 0; i < times; i++) { splitStr += ch; } // Generate the split string xx in the above case. var str = myArray.join(''); // Join array items into a string var array = str.split(splitStr); // Split the string based on split string var result = {}; // iterate on the array starting from index 1 as at index 0 will be string before split str for (var i = 1 ; i < array.length; i++) { if(array[i] !== "") { result[array[i].substring(0,1)] = ''; // A map in order to avoid duplicate values } } return Object.keys(result); // return the keys } console.dir(search('x',2));
You can create an additional function isItGood
like this:
var myArray = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x']; var arrLength = myArray.length; for (var i = 0; i < arrLength; i++) { isItGood(myArray, i, 'x', 2); }; function isItGood(arr, i, elem, total) { for ( var j = 0 ; j < total ; j++ ) { if ( i + total >= arr.length || arr[i+j] != elem ) { return; } } console.log(arr[i+total]); // just to see the result (no need to open a console) document.getElementById('p').innerHTML+=("<br/>"+arr[i+total]); }
<p id="p">Result: </p>
Here is a straightforward iterative solution. We maintain an array consecutive
of consecutive elements. If that array gets to length 2, then the next element is printed and consecutive
is reset.
var arr = ['a', 'x', 'b', 'x', 'x', 'p', 'y', 'x', 'x', 'b', 'x', 'x'];
var REPEATS_NEEDED = 2;
var consecutive = [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (consecutive.length === REPEATS_NEEDED) {
console.log(arr[i]);
consecutive = [arr[i]];
continue;
}
// either add to or reset 'consecutive'
if (arr[i] === consecutive[0]) {
consecutive.push(arr[i]);
} else {
consecutive = [arr[i]];
}
};
Try using for
loop using variables referencing previous index, current index, next index of array
var myArray = ["a", "x", "b", "x", "x", "p", "y", "x", "x", "b", "x", "x"]; for (var res = [], curr = 0, prev = curr - 1, match = curr + 1 ; curr < myArray.length - 1; curr++, prev++, match++) { if (myArray[curr] === myArray[prev]) res.push(myArray[match]); }; console.log(res); document.body.textContent = res;
If I had to write this in Scala instead of JavaScript I could just do it in one line. myArray.sliding(3).filter(l => l(0) == 'x' && l(1) == 'x').map(l => l(2))
So I guess I could do it the same way in JS if I implement the sliding function myself. eg
function sliding(array, n, step) {
if(!step) step = 1;
var r = [];
for(var i = 0; i < array.length - n + 1; i += step) {
r.push(array.slice(i, i + n));
}
return r;
}
var result = sliding(myArray, 3).filter(l => l[0] === "x" && l[1] === "x").map(l => l[2]);
The only downside here is that this runs slower than a more iterative approach. But that only matters for very big arrays.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.