Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move to prev/next element of an array

Tags:

Let's say we have a list of integers:

var fibonacci = [1,1,2,3,5,8,13,21]; 

I want to be able to get the next and previous element (just to move the element pointer, without modifying the array) in following manner (example, might go without prototype to redefine the Array interface but why not):

fibonacci.prev(); // returns false fibonacci.next(); // returns 1 fibonacci.next(); // returns 1 fibonacci.next(); // returns 2 fibonacci.next(); // returns 3 fibonacci.next(); // returns 5 fibonacci.next(); // returns 8  fibonacci.prev(); // returns 5  fibonacci.next(); // returns 8 fibonacci.next(); // returns 13 fibonacci.next(); // returns false 
like image 284
ddinchev Avatar asked Sep 12 '12 14:09

ddinchev


People also ask

How do you shift elements in an array?

Create a temp variable and assign the value of the original position to it. Now, assign the value in the new position to original position. Finally, assign the value in the temp to the new position.

How do you replace an element in an array with another?

Replace an Element in an Array using Array.Use the indexOf() method to get the index of the element you want to replace. Call the Array. splice() method to replace the element at the specific index. The array element will get replaced in place.


1 Answers

If you want to keep the list as an Array, you'll have to change its [[prototype]] to make it look like an iterable collection:

Array.prototype.next = function() {     return this[++this.current]; }; Array.prototype.prev = function() {     return this[--this.current]; }; Array.prototype.current = 0; 

Now every Array will have the methods prev and next, and the current property, which points to the "current" elements. A caveat: the current property can be modified, thus leading to impredictable results.

Post scriptum: I don't recommend to make prev and next return false when the index is out of range. If you really want to, you can change the methods to something like:

Array.prototype.next = function() {     if (!((this.current + 1) in this)) return false;     return this[++this.current]; }; 

UPDATE mid-2016

I'm updating this answer because it seems it's still receiving views and votes. I should have clarified that the given answer is a proof of concept and in general extending the prototype of native classes is a bad practice, and should be avoided in production projects.

In particular, it's not much because it's going to mess with for...in cycles - which should always be avoided for arrays and it's definitely a bad practice for iterating through their elements - and also because since IE9 we can reliably do this instead:

Object.defineProperty(Array.prototype, "next", {     value: function() { return this[++this.current]; },     enumerable: false }); 

The main problem is that extending native classes is not future-proof, i.e. it may happen that ECMA will introduce a next method for arrays that will probably be incompatible with your implementation. It already happened even with very common JS frameworks - the last case was MooTools' contains array extension which led ECMA to change the name to includes (bad move, IMO, since we already have contains in DOMTokenList objects like Element.classList).

That being said, it's not that you must not extend native prototypes, but you should be aware of what you're doing. The first advice I can give you is to choose names that won't clash with future standard extensions, e.g. myCompanyNext instead of just next. This will cost you some code elegance but will make you sleep sound.

Even better, in this case you can effectively extend the Array class:

function MyTraversableArray() {     if (typeof arguments[0] === "number")         this.length = arguments[0];     else this.push.apply(this, arguments);      this.current = 0; } MyTraversableArray.prototype = []; MyTraversableArray.prototype.constructor = MyTraversableArray; MyTraversableArray.prototype.next = function() {     return this[++this.current]; }; MyTraversableArray.prototype.prev = function() {     return this[--this.current]; }; 

In ES6, moreover, it's easier to extend native classes:

class MyTraversableArray extends Array {     next() {         return this[++this.current];     } } 

Alas, transpilers have a hard time with native class extensions, and Babel removed its support. But it's because they can't exactly replicate some behaviours which have no influence in our case, so you can stick with the above old ES3 code.

like image 167
MaxArt Avatar answered Nov 03 '22 08:11

MaxArt