Why doesn't JavaScript have a last method? [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Its kinda weird that the JavaScript Array class does not offer a last method to retrieve the last element of an array. I know the solution is simple (Ar[Ar.length-1] ), but, still, this is too frequently used.
Any serious reasons why this is not incorporated yet?

You can do something like this:
[10, 20, 30, 40].slice(-1)[0]
console.log([10, 20, 30, 40].slice(-1)[0])
The amount of helper methods that can be added to a language is infinite. I suppose they just haven't considered adding this one.

It's easy to define one yourself. That's the power of JavaScript.
if(!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 1];
}
}
var arr = [1, 2, 5];
arr.last(); // 5
However, this may cause problems with 3rd-party code which (incorrectly) uses for..in loops to iterate over arrays.
However, if you are not bound with browser support problems, then using the new ES5 syntax to define properties can solve that issue, by making the function non-enumerable, like so:
Object.defineProperty(Array.prototype, 'last', {
enumerable: false,
configurable: true,
get: function() {
return this[this.length - 1];
},
set: undefined
});
var arr = [1, 2, 5];
arr.last; // 5

Because Javascript changes very slowly. And that's because people upgrade browsers slowly.
Many Javascript libraries implement their own last() function. Use one!

i = [].concat(loves).pop(); //corn
icon cat loves popcorn

Another option, especially if you're already using UnderscoreJS, would be:
_.last([1, 2, 3, 4]); // Will return 4

Array.prototype.last = Array.prototype.last || function() {
var l = this.length;
return this[l-1];
}
x = [1,2];
alert( x.last() )

Came here looking for an answer to this question myself. The slice answer is probably best, but I went ahead and created a "last" function just to practice extending prototypes, so I thought I would go ahead and share it. It has the added benefit over some other ones of letting you optionally count backwards through the array, and pull out, say, the second to last or third to last item. If you don't specify a count it just defaults to 1 and pulls out the last item.
Array.prototype.last = Array.prototype.last || function(count) {
count = count || 1;
var length = this.length;
if (count <= length) {
return this[length - count];
} else {
return null;
}
};
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.last(); // returns 9
arr.last(4); // returns 6
arr.last(9); // returns 1
arr.last(10); // returns null

Here is another simpler way to slice last elements
var tags = [1, 2, 3, "foo", "bar", "foobar", "barfoo"];
var lastObj = tags.slice(-1);
lastObj is now ["barfoo"].
Python does this the same way and when I tried using JS it worked out. I am guessing string manipulation in scripting languages work the same way.
Similarly, if you want the last two objects in a array,
var lastTwoObj = tags.slice(-2)
will give you ["foobar", "barfoo"] and so on.

pop() method will pop the last value out. But the problem is that you will lose the last value in the array

Yeah, or just:
var arr = [1, 2, 5];
arr.reverse()[0]
if you want the value, and not a new list.

Related

Rotate multiple banner images [duplicate]

By default the indexing of every JavaScript array starts from 0. I want to create an array whose indexing starts from 1 instead.
I know, must be very trivial... Thanks for your help.
It isn't trivial. It's impossible. The best you could do is create an object using numeric properties starting at 1 but that's not the same thing.
Why exactly do you want it to start at 1? Either:
Start at 0 and adjust your indices as necessary; or
Start at 0 and just ignore index 0 (ie only use indices 1 and up).
A simple solution is to fill the zeroth item:
var map = [null, 'January', 'February', 'March'];
'First month : ' + map[1];
Semantically it would be better to use an object:
var map = {1:'January', 2:'February', 3:'March'};
'First month : ' + map[1];
Note these keys are not ints actually, object keys are always strings.
Also, we can't use dot notation for accessing. (MDN - Property Accessors)
I'd choose the first solution, which I think is less confusing.
Since this question also pops up for a Google search like "javascript start array at 1" I will give a different answer:
Arrays can be sliced. So you can get a sliced version of the Array like this:
var someArray = [0, 1, 2, 3];
someArray.slice(1);
[1, 2, 3]
someArray.slice(2, 4);
[2, 3]
Source: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/slice
You could use delete to remove the first element like so:
let arr = ['a','b','c'];
delete arr[0];
console.log(arr[0]);
console.log(arr[1]);
Or just not define it at all:
let arr = [,'b','c'];
console.log(arr[0]);
console.log(arr[1]);
If you want to make sure that you always get the first truthy element regardless of the index and have access to ES6 you can use:
arr.find(Boolean)
The question asks "How to create an array in JavaScript whose indexing starts at 1". The accepted answer states "It isn't trivial. It's impossible."
This is true, and should be understood for good reason. However, you can create an array and omit setting the first element, in which case it will still exist (hence the accepted answer being correct) but it'll be marked as empty for you.
let usernames = ['bob', 'sally', 'frank']
let myArray = [];
let arrayIndex = 1;
usernames.map(username => {
myArray[arrayIndex] = username;
arrayIndex++;
})
console.log(myArray);
Array(4) [ <1 empty slot>, "bob", "sally", "frank" ]
1: "bob"
2: "sally"
3: "frank"
​length: 4
Notice that the length is "4".
console.log(myArray[0]);
undefined
Using this, there's a quirk in our favour whereby using Object.keys() on an array doesn't return empty (undefined) elements. So with the above array:
console.log(Object.keys(myArray).length);
3
Note: This is arguably a little hacky so use it with caution.
As zero of something rarely exists in our world, doing this might be useful where you are only going to access pre-defined indexes. An example would be if you have pages of a book. There isn't a page 0 as that makes no sense. And if you are always access a value directly, e.g.
const currentPage = pages[1];
Then this is fine in my opinion, as long as the code shows intent. Some will argue that ignoring a valid array index is futile, and I don't fully disagree. However, it's also futile and very annoying when I want to get page 35 of a book and the array index is 34. Meh!
When you loop your (dodgy) array with map it ignores the 0 index you didn't want:
myArray.map((value, index) => {
console.log(index);
console.log(value);
})
1
bob
2
sally
3
frank
For general use however, you should use index 0, so when you loop some data and spit things out you're not going to get caught out by the first one being empty.
Okay, according to #cletus you couldn't do that because it's a built-in javascript feature but you could go slightly different way if you still want that. You could write your own index-dependent functions of Array (like reduce, map, forEach) to start with 1. It's not a difficult task but still ask yourself: why do I need that?
Array.prototype.mapWithIndexOne = function(func) {
const initial = []
for (let i = 1; i < this.length + 1; i++) {
initial.push(func(this[i - 1], i))
}
return initial
}
const array = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
console.log(array.mapWithIndexOne((element, index) => `${element}-${index}`))
// => ["First-1", "Second-2", "Third-3", "Fourth-4", "Fifth-5"]
Codepen: https://codepen.io/anon/pen/rvbNZR?editors=0012
Using Array.map
[,1,2,3].map((v, i) => ++i)
Just wanted to point out that an index in c ish languages is also the offset from the first element. This allows all sorts of offset math where you don't have to subtract 1 before doing the math, only to add the 1 back later.
if you want a "1" array because the indexes are mapped to other values, that's the case for an enumeration or a hash.
First add this function to your javascript codes:
var oneArray = function(theArray)
{
theArray.splice(0,0,null);
return theArray
}
Now use it like this:
var myArray= oneArray(['My', 'name', 'is', 'Ram']);
alert(myArray[1]); << this line show you: My
See live demo
Just prepend a null:
a = [1, 2, 3, 4]
a.unshift(null)
a[3] // 3
Simple, just make two changes to the classic Javascript for loop.
var Array = ['a', 'b', 'c'];
for (var i = 1; i <= Array.length; i++) {
//"i" starts at 1 and ends
//after it equals "length"
console.log(i);
}

Taking numbers from a const array and adding +2 to each number | Must Use for Loop

const addTwo = [1, 2, 3, 4, 5];
for (let i = addTwo.length; i >= 5; i++) {
addTwo = addTwo += 2 //I know this does not work
}
console.log(addTwo); // -> should print [3, 4, 5, 6, 7];
Hi there,
New to js and working on using an array with a for loop. In this problem it's asking me to specifically use a for loop to get a solution. I was able to get my answer using splice. But, to be honest I thought this was a little heavy handed and lazy to me. I didn't think it was going to help me learn anything. I have exhausted many options online. Looking at various videos on the subject of for loops.
I just felt I could use some help from the pros. I get a "Type Error on line 4: Assignment to constant variable." Now, as I understand you can't change a constant variable. Any ideas what I could use as a beginner? Thank you for your patience and help!
You need to assign to the array element, not the whole array. And the indexes in the loop are wrong. You should start from 0 and go up to the length-1. Your loop will repeat infinitely because i >= 5 is always true when you start with i = 5 and keep adding 1 to it.
const addTwo = [1, 2, 3, 4, 5];
for (let i = 0; i < addTwo.length; i++) {
addTwo[i] += 2;
}
console.log(addTwo);

JS .includes() with more than one values of array? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have an array of numbers like A = ['1', '34', '23', '55'] and want to use .includes() to find true or false. However, my tested values are in array like B = ['3', '1', '543', '33']
I'd tried to do A.includes(B) but it seems it is not working. A.includes('1', '123') returns true. How can I use my Array B to do the same?
I wanted to Check if the array A has at least one of the array B’s value then return true. Apology for missing this part!
If I understand you correctly, you're looking to do A.includes(B), but your inputs are stored in arrays. In this case, simply loop through the values and call includes() on the elements:
const A = ['1', '34', '23', '55'];
const B = ['3', '1', '543', '33'];
for (var i = 0; i < A.length; ++i)
console.log(A[i].includes(B[i]));
If you need to check if all values in B are in A, you can do it like below:
B.every(item => A.includes(item)) // true or false
includes() does not work this way. Per the Mozilla docs:
arr.includes(valueToFind[, fromIndex])
Where valueToFind is a single value and fromIndex is the index to start looking from. (In your case it looks like it ignored that because it was a string; otherwise it would have returned false.)
If what you want is to find if array A contains every element of array B, there's no standard library function that does exactly that. Here's what you can do:
function containsAll(container, contained) {
return contained.every(item => container.includes(item))
}
containsAll(A, B);
If I understand you correct you want to check if array B all of it's element includes
in array A or not it would be like this using every
B.every((el) => A.includes(el))
let A = [1, 2, 3], B = [2, 3, 4]
let result = B.every((el) => A.includes(el))
console.log(result)
and if you want at least one element from the second array to be in the first one you could do like this using some
B.some((el) => A.includes(el))
let A = [1, 2, 3], B = [2, 3, 4];
let result = B.some((el) => A.includes(el))
console.log(result)

benefits of map over for loop in terms of safety [duplicate]

This question already has answers here:
Imperative vs Declarative code [closed]
(3 answers)
Closed 4 years ago.
I have a vague understanding of what does it mean "provide immutability" when talking about using map over for loop. Because calling Array.prototype.map on array does not prevent you from altering original array. Let's say we have single threaded asynchronous program. In these circumstances is there an "immutability" benefit that map provides over for loop?
I can imagine the following code:
function A() {
const arr = [1, 2, 3, 4, 5]
const anotherArr = arr.map((e, i) => {
arr[i] = 'changed'
// here goes some asynchronous code
return e * 2
})
// now arr is ['changed', 'changed', 'changed', 'changed', 'changed']
// and anotherArr is [2, 3, 6, 8, 10]
}
function B() {
const arr = [1, 2, 3, 4, 5]
const anotherArr = []
for (let i = 0, len = arr.length; i < len; i++) {
anotherArr[i] = arr[i] * 2
arr[i] = 'changed'
// here goes some asynchronous code
}
// and again:
// now arr is ['changed', 'changed', 'changed', 'changed', 'changed']
// and anotherArr is [2, 3, 6, 8, 10]
}
I guess that probably in function B anotherArr is created manually before populating. Therefore something in the same scope can alter it before for loop is completed. So my question is: "Is there a benefit of using map over for loop in single threaded asynchronous environment in terms of safety"?
Editing
I rephrase my question: "Is there some kind of immutability that Array.prototype.map function
provides (because it belongs to functional paradigm)".
As I understand now the map function in javascript is not about immutability,
it is about hiding some implementation details (how resulting array is constructed).
So map function is a delclarative way of doing things. for loop is an imperative
way of doing things (which brings more freedom and more responsibility I guess).
map, reduce, filter, forEach, etc.
Methods above, in my mind, is nice for FP(functional programming).
Of course, you can use them instead of normal for loop,
but normal for loop is faster than them(https://hackernoon.com/javascript-performance-test-for-vs-for-each-vs-map-reduce-filter-find-32c1113f19d7).
So in my idea, if your don't care performance, use map, reduce, etc. is elegant and will get lesser and more readable code.

JavaScript unique method for array prototype [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Clarification:
As some people have pointed out, this does look like a "Is this code ok"-kind of question. The main thing I'm actually curious about is this: how does the .hasOwnProperty method work?I mean: IE's JScript engine (<9 at least) doesn't always use hash-tables, so I assume it does little more than iterate over all properties of that object, and then checks to see if it gets those properties from another object higher up the prototype-chain. Is this a fair assumption to make? After all: at some level every code gets translated into loops and branches, but if IE doesn't do hash-tables, doesn't that mean .hasOwnProperty is just some sugar, just there so you don't have to write the loop? I think I got this notion from one of DC's blog-posts or video's and it could well be that he was talking about arrays, and the quirky things they are (or rather: can be) in JS. I can't find the video/blog-post(?) ATM. And seeing as JS Arrays are often abused, as many of you I think will agree, I thought the answers to this question could serve as a decent reference. That's why I didn't post it on codereview.
As far as current answers go, and since my question started of from the wrong angle (focussing on the code more than the mechanisms behind it), let me just be so corny as to thank you all for pointing out the issues I didn't think of.
Recently, I augmented the array prototype for a script I was working on (don't shoot, just yet). In order not to reinvent the wheel, I went and searched for some examples of how other people went about it.
Strangly This is quite common, which is plainly needlessly complex. I also found this, as an alternative, other than the poster being rather smug about his fast algorithm I still feel there is room for improvement.
I know I might come across as a smug wise-guy now, my unique method actually looks like this:
Array.prototype.unique = function()
{
'use strict';
var i,obj,ret;
ret = [];
obj = {};
for (i=0;i<this.length;i++)
{
if (!obj.hasOwnProperty(this[i]))
{
ret.push(this[i]);
obj[this[i]] = i;
}
}
return ret;
};
This way, there just is no need for a second loop AFAIK, is there? Unless, of course, the hasOwnProperty method is dead slow, but somehow I doubt that, in this case: the chain can only go back 1 level, to the Object.prototype.
The second link I posted contains some statistics and speed-comparisons, but as we all know they mean next to nothing in the real world. Could anyone point me in the direction of good article on JS and benchmarking (apart from the one on John Resig's blog?
So, just out of curiosity: Does any one of you see a problem with this method? some more info: Object.prototype: unchanged, undefined is undefined, no globals no frameworks, and this method isn't blindly implemented (if (!Array.prototype.unique){...})
Here is an implementation that considers type correctly, is much faster than the naive nested loops, and maintains the original array's order:
Array.prototype.unique = function(){
var r, o, i, j, t, tt;
r = [];
o = {};
for(i = 0; i < this.length; i++){
t = this[i];
tt = o[t] = o[t] || [];
for(j = 0; j < tt.length; j++)
if(tt[j] === this[i])
break;
if(j == tt.length)
r.push(tt[j] = t);
}
return r;
}
I made a JSPerf to compare these implementations.
unique1 is the nested loops.
unique2 is the fast algorithm you linked to.
unique3 is your version.
unique4 is mine.
Added
unique5 is Kooilnc's answer
unique6 is primvdb's answer
While unique2 is the fastest, it has the problem that it considers "1" and 1 as equal. unique4 comes in third for speed but is much faster than unique1 and gives correct output. All four variations actually give different output:
=> [1, "1", 1, 2, 3, 4, 1, 2, 3, "2", "3", "4", "true", "true", true].unique1()
// ["1", 4, 1, 2, 3, "2", "3", "4", "true", true]
=> [1, "1", 1, 2, 3, 4, 1, 2, 3, "2", "3", "4", "true", "true", true].unique2()
// [1, "2", "3", "4", true]
=> [1, "1", 1, 2, 3, 4, 1, 2, 3, "2", "3", "4", "true", "true", true].unique3()
// [1, 2, 3, 4, "true"]
=> [1, "1", 1, 2, 3, 4, 1, 2, 3, "2", "3", "4", "true", "true", true].unique4()
// [1, "1", 2, 3, 4, "2", "3", "4", "true", true]
Although not widely supported, you can use a Set (from ECMAScript Harmony). It's native so it shouldn't have that much of a performance impact (e.g. there is no need to look for the actual index like indexOf does). The main advantage is that you can seamlessly use it to keep track of which items you've already had, including objects, and you can take account for same objects:
Array.prototype.unique = function() {
'use strict';
var ret = [];
var used = new Set();
for (var i = 0; i < this.length; i++) {
if (!used.has(this[i])) {
ret.push(this[i]);
used.add(this[i]);
}
}
return ret;
};
var a = {};
var b = {};
[1, 2, 1, a, a, null, b].unique(); // [1, 2, a, null, b]
Looks fine, but as Felix Kling noted it only works with arrays containing primitives. This one is a bit more complex, but works for all types I think:
Array.prototype.unique = function(){
'use strict';
var im = {}, uniq = [];
for (var i=0;i<this.length;i++){
var type = (this[i]).constructor.name,
// ^note: for IE use this[i].constructor!
val = type + (!/num|str|regex|bool/i.test(type)
? JSON.stringify(this[i])
: this[i]);
if (!(val in im)){uniq.push(this[i]);}
im[val] = 1;
}
return uniq;
}
//testing
var test = [1,2,'string',[1,2,3],'string','1','2',
{yada:'yada'},/[a-z]/i,2,1,1,2,[1,2,3],
false, new Date(),/[a-b]/i,5,/[a-z]/i,'false']
,testunique = test.unique();
//=> testunique now
// [1,2,string,[1,2,3],1,2,[object Object],
// /[a-z]/i,false,Mon Aug 20 2012 20:20:11 GMT+0200,
// /[a-b]/i,5,false]

Categories