I have an array in JavaScript that have defined these values:
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
And when I call a function the first time function, I need to get this:
1
2
3
Calling it again I need to get:
4
5
6
Calling it again:
7
8
9
Calling it again:
10
1
2
Calling again:
3
4
5
And so on. You got the point, showing 3 values from the array and if we are at the end of array, read from the beginning... I have an app that has remote control and has down and up keys. When the user presses the down button to get these values from an array as described in the above example, if the user presses the up button it needs to go back from an example...so reading the array in a loop (at end, the array is read from the beginning, but always shows three values).
I try using this:
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
if (i<(6)) {
console.log(myStringArray[i]);
}
}
But the next time I call this code, it shows from the beginning values of the array, not continue to read others value...do I need a second counter?
8 Answers 8
If you are OK with manipulating your original array as you loop through it you could splice and concat similar to below (or you could use a clone of the array if you need to persist the original array):
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
var loopByX = function(x){
var y = myStringArray.splice(0,x);
myStringArray = myStringArray.concat(y);
return y;
}
console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));
console.log(loopByX(3));
If you want to go bi-directional (is that what you call it?), as mentioned in the comments, you could do it as below which then gives you the ability to go backwards or forward and the flexibility to do so in an arbitrary number:
var myStringArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
var loopByX = function(x) {
var len = myStringArray.length;
// Ensure x is always valid but you can add any behaviour here in that case yourself. As an example I return an empty array.
if (Math.abs(x) > len) {
return [];
}
var y = x > 0 ? myStringArray.splice(0, x) : myStringArray.splice(len + x, len);
myStringArray = x > 0 ? myStringArray.concat(y) : y.concat(myStringArray);
return y;
}
console.log(loopByX(20)); // invalid number
console.log(loopByX(-20)); // invalid number
console.log(loopByX(-3));
console.log(loopByX(-6));
console.log(loopByX(3));
console.log(loopByX(4));
6 Comments
myStringArray = x > 0 ? myStringArray.concat(y) : y.concat(myStringArray) it will also work backwardsMath.abs(x) but you can tweak that to your needs.You could take a function which slices three elements and if not possible, it takes the needed first values of the array as well.
function take3() {
var temp = array.slice(index, index += 3)
index %= array.length;
console.log(temp.concat(temp.length < 3 ? array.slice(0, index) : []).join(' '));
}
var array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
index = 0;
<button onclick="take3()">take 3</button>
With a mapping of a dynamic count.
function take(length) {
console.log(Array.from({ length }, _ => array[++index, index %= array.length]));
}
var array = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
index = -1;
<button onclick="take(3)">take 3</button>
1 Comment
Your variable i is local to the for loop which means it basically resets every time the loop is started. So first make your variable i global.
var i=0;
function employeeNames(){
var empList = ["1","2","3","4","5","6","7","8","9","10"];
var output = [];
var j=0;
while(j<3)
{
output.push(empList[i])
i=(i+1)%empList.length;
j++;
}
return output;
}
console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());
console.log(employeeNames());
Comments
If you want the immutable way to achieve your circular looping
function loopArray(arr, step=3) {
let i = 0;
return function inner() {
for (let j = 0; j < step; j++) {
console.log(arr[i]);
i = (i + 1) % arr.length;
}
};
}
const func = loopArray(["1","2","3","4","5","6","7","8","9","10"], 3);
func();
func();
func();
func();
func();
Comments
The fancy solution with generator functions:
function* cycle(arr) {
let i=0;
while (true) {
yield arr[i++];
i %= arr.length;
}
}
function* chunksOf(n, iterable) {
let chunk = [];
for (const x of iterable) {
chunk.push(x)
if (chunk.length >= n) {
yield chunk;
chunk = [];
}
}
if (chunk.length > 0)
yield chunk;
}
function toFunction(iterator) {
return () => iterator.next().value;
}
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
const f = toFunction(chunksOf(3, cycle(myStringArray)));
console.log(f());
console.log(f());
console.log(f());
// ...
Comments
@Igor Petev, JavaScript's closures are a nice concept that you can use to solve your problem.
Please read JavaScript's Closures - w3schools article. It's really nice and excellent.
I have used the concept of closures to solve this problem. Please leave a comment if you don't understand my code or anything else related to this problem.
Please have a look at the below code.
var get3items = (function () {
var index = 0;
var myStringArray = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"];
var len = myStringArray.length
return function () {
for(var count = 0; count < 3; count += 1)
{
console.log(myStringArray[index]);
if(index == (len - 1))
{
index = 0;
}
else {
index += 1;
}
}
}
})();
get3items (); // First call
console.log()
get3items (); // Second call
console.log()
get3items (); // Third call
console.log()
get3items (); // Fourth call
console.log()
get3items (); // Fifth call
/*
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
*/
2 Comments
How about using a generator:
function* get3() {
var myStringArray = ["1","2","3","4","5","6","7","8","9","10"];
var index = 0;
while (true) {
yield [0, 1, 2].map(i => myStringArray[(index + i) % myStringArray.length])
index = (index + 3) % myStringArray.length;
}
}
Calling this function returns an object which you can call .next() on, to get the next set of 3:
var getter = get3();
console.log(getter.next().value); // ["1","2","3"]
console.log(getter.next().value); // ["4","5","6"]
console.log(getter.next().value); // ["7","8","9"]
// etc.
Comments
function* employeeNames(){
var empList = ["1","2","3","4","5","6","7","8","9","10"];
for(var i =0; i<=empList.length; i++){
yield empList[i];
}
}
var emp;
emp = employeeNames();
It uses a generator function...
iand build the logic from here. It's just a matter of looping 3 times in a circular way.