Get last element of a JSON object in JavaScript - javascript

I got a json object in JavaScript like:
var json = {"20121207":"13", "20121211":"9", "20121213":"7", "20121219":"4"};
without knowing the name of the last key. (The keys are in ascending order)
How can I read the value (and key) of the last element?

var highest = json[ Object.keys(json).sort().pop() ];
Object.keys (ES5, shimmable) returns an array of the object's keys. We then sort them and grab the last one.
You can't ensure order in a for..in loop, so we can't completely rely on that. But as you said the keys are in ascending order, we can simply sort them.

Try this:
var lastKey;
var json = {"20121207":"13", "20121211":"9", "20121213":"7", "20121219":"4"};
for(var key in json){
if(json.hasOwnProperty(key)){
lastKey = key;
}
}
alert(lastKey + ': ' + json[lastKey]);

If you don't need to support old JS engines:
var lastKey = Object.keys(json).sort().reverse()[0];
var lastValue = json[lastKey];
Don't assume the keys are in order. Get the keys, and then sort them, and then grab that largest value after the sort.

Object keys are typically unordered, but looking at the keyset you are using, I made the assumption that you are looking for the highest date in the json keys:
var json = {"20121207":"13", "20121211":"9", "20121213":"7", "20121219":"4"};
function getMaxFromKeys(json) {
var m;
for (var i in json) {
if (json.hasOwnProperty(i)) {
m = (typeof m == 'undefined' || i > m) ? i : m;
}
}
return m;
}
var latestDate = getMaxFromKeys(json);

ECMCA script specifications (javascript specifications) do not require browsers to maintain order of the properties of an object.
Related to for-in this is what ECMCA 5 specs say:
"The mechanics and order of enumerating the properties (step 6.a in
the first algorithm, step 7.a in the second) is not specified."
Related to the Object.keys method:
"If an implementation defines a specific order of enumeration for the
for-in statement, that same enumeration order must be used in step 5
of this algorithm."
It does not make sense to say get the last defined property. You can sort the properties based on the name and get the last one, but if what you want is order then keep an array.

let obj = <your_object>
let last_key = Object.keys(obj)[Object.keys(obj).length - 1]
let last_value = <your_object>.last_key
OR
let last_value = Object.values(obj)[Object.values(obj).length - 1]

getJsonLastElement(json)
{
let len = json.length
return json[len - 1]
}

Related

JavaScript - Filter array with mutation

I want to filter a array by keeping the same array without creating a new one.
with Array.filter() :
getFiltersConfig() {
return this.config.filter((topLevelConfig) => topLevelConfig.name !== 'origin')
}
what is the best way to get the same result by filtering by value without returning a new array ?
For completeness, I thought it might make sense to show a mutated array variant.
Below is a snippet with a simple function mutationFilter, this will filter the array directly, notice in this function the loop goes in reverse, this is a technique for deleting items with a mutated array.
Also a couple of tests to show how Array.filter creates a new array, and mutationFilter does not.
Although in most cases creating a new array with Array.filter is normally what you want. One advantage of using a mutated array, is that you can pass the array by reference, without you would need to wrap the array inside another object. Another advantage of course is memory, if your array was huge, inline filtering would take less memory.
let arr = ['a','b','a'];
let ref = arr; //keep reference of original arr
function mutationFilter(arr, cb) {
for (let l = arr.length - 1; l >= 0; l -= 1) {
if (!cb(arr[l])) arr.splice(l, 1);
}
}
const cond = x => x !== 'a';
const filtered = arr.filter(cond);
mutationFilter(arr, cond);
console.log(`ref === array -> ${ref === arr}`);
console.log(arr);
console.log(`ref === filtered -> ${ref === filtered}`);
console.log(filtered);
I want to filter a array by keeping the same array without creating a new one.
what is the best way to get the same result by filtering by value without returning a new array ?
I have an answer for the second criterion, but violates the first. I suspect that you may want to "not create a new one" specifically because you only want to preserve the reference to the array, not because you don't want to create a new array, necessarily (e.g. for memory concerns).
What you could do is create a temp array of what you want
var temp = this.config.filter((topLevelConfig) => topLevelConfig.name !== 'origin')
Then set the length of the original array to 0 and push.apply() the values "in-place"
this.config.length = 0; //clears the array
this.config.push.apply(this.config, temp); //adds what you want to the array of the same reference
You could define you custom method like so:
if(!Array.prototype.filterThis){
Array.prototype.filterThis = function (callBack){
if(typeof callBack !== 'function')
throw new TypeError('Argument must of type <function>');
let t = [...this];
this.length = 0;
for(let e of t) if(callBack(e)) this.push(e);
return this;
}
}
let a = [1,2,3,4,5,5,1,5];
a.filterThis(x=>x!=5);
console.log(a);
Warning: Be very cautious in altering built in prototypes. I would even say unless your making a polyfill don't touch. The errors it can cause can be very subtle and very hard to debug.
Not sure why would you want to do mutation but if you really want to do it, maybe assign it back to itself?
let arr = ['a','b','a'];
arr = arr.filter(x => x !== 'a');
console.log(arr)

Get first element in array with index not starting from 0

I'm using a javascript library which returns arrays not starting from zero like starting from 26 or 1500, what i want to do is a method to get the first element in that array regardless of the index number starting with 0 or any other number.
Are they any method to do this in javascript ?
I suggest to use Array#some. You get the first nonsparse element and the index. The iteration stops immediately if you return true in the callback:
var a = [, , 22, 33],
value,
index;
a.some(function (v, i) {
value = v;
index = i;
return true;
});
console.log(index, value);
The information below is generally useful, but for the problem the OP listed, Nina's answer is by far a better solution.
Those are called sparse arrays and they're one of the few situations where you may want to use for-in on an array.
Remember that arrays are objects in JavaScript, and array entries are properties keyed by names (array indexes) that meet certain criteria. So we can use the features that let us discover the properties on an object to find the indexes on your sparse array.
for-in example:
for (var n in theArray) {
if (theArray.hasOwnProperty(n) && isArrayIndex(n)) {
// Use theArray[n]
}
}
This answer shows how you can determine that n is an array index as opposed to being some other property. A very technical definition would be
function isArrayIndex(n) {
return /^0$|^[1-9]\d*$/.test(n) &&
n <= 4294967294;
}
...but a definition that's good enough for most of us would be
function isArrayIndex(n) {
return !isNaN(parseInt(n, 10));
}
Similarly, you can use Object.keys; since it only looks at own enumerable properties, you don't need the hasOwnProperty check:
Object.keys(theArray).forEach(function(n) {
if (isArrayIndex(n)) {
// ...
}
});
Note that officially, neither of those is in any particular order, not even in ES2015 ("ES6"). So in theory, you could see the indexes out of numeric order. In the real world, I've never seen an even vaguely-modern JavaScript engine that returned array indexes out of order. They're not required to, but every one I've tried does.
So officially, you would need to get a full list and then find the minimum value in it:
var min = Object.keys(theArray).reduce(function(min, n) {
var i = parseInt(n, 10);
return isNaN(i) || (min !== undefined && min > i) ? min : i;
}, undefined);
That'll given you undefined if the array is empty, or the min index if it isn't. But if you want to make the assumption you'll get the keys in numeric order:
// Makes an assumption that may not be true
var min = +Object.keys(theArray).filter(isArrayIndex)[0];
If you're using a JavaScript engine that's entirely up-to-date, you can rely on the order returned by Object.getOwnPropertyNames, which is required to list the array indexes in order.
var min = +Object.getOwnPropertyNames(theArray).filter(isArrayIndex)[0];
It may be useful to use a filter function on the array to get back a normalised array.
var fullArray = array.filter(function(n){
return n != undefined;
});
fullArray[0]
The answers here may help you decide Remove empty elements from an array in Javascript
I guess one alternative to Array.prototype.some() is the Array.prototype.findIndex() method. These are much faster than filter alone and will keep your array and indices untouched.
var arr = new Array(1000),
fi = -1;
arr[777] = 1453; // now we have a nice sparse array
fi = arr.findIndex(f => f !== void 0); // void 0 is the perfect undefined
console.log(fi);
console.log(arr[fi]);
With this piece of code you can find first assigned value index and then get the value from your array:
var a = [, , 22, 33];
var value = a.find((v, i) => i in a);
console.log(value);
/* ---------------------------------------------- */
var i = 0
while (!(i in a) && i < a.length) i++; // If i === a.length then the array is emtpy
console.info(i, a[i]);
First implementation uses Array.prototype.find which makes less variable usage so this is cleaner but to find the index you should call indexOf over the array.
But the second one is a little bit old fashioned but give the chance of having index without extra efforts.
BTW Nina's seems better. (can make it shorter?)
const arr = [0,1,2]
// using destructuring to get the first element
let [first] = arr
// plus: using destructuring to get the last element
let [first] = [...arr].reverse()

Get the length of an array within a JSON object

I want to find out how many items are in my JSON object. I have seen many answers but they all deal with a common value to loop through. I am wanting the results to tell me that there are 2 items in this object. Any help would be great!
[{"manager_first_name":"jim","manager_last_name":"gaffigan"}]
You could use Object.keys in newer browsers. It would return an array of all the keys in the object, and that array would have a length property that will tell you how many items there are in the object :
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var length = Object.keys(arr[0]).length;
FIDDLE
In non-supporting browsers, you have to iterate
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var i = 0;
for (var key in arr[0]) i++;
FIDDLE
You can do this:
var arr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}],
length = 0,
obj = arr[0]; // Get first obj from array
for(var k in obj){
if( obj.hasOwnProperty(k) ) {
length++;
}
}
console.log(length); // Shows 2
You should use hasOwnProperty because you can also extend an Object with functions, there could otherwise also be count als keys.
Links:
hasOwnProperty
Try
var jsonArr = [{"manager_first_name":"jim","manager_last_name":"gaffigan"}];
var itemCount = JSON.stringify(jsonArr).split('":"').length - 1;
This is, of course, a rather coarse(and unreliable) way of doing it, but if you just want the item count, this should work like a charm.

Can't reference array by index

I have an array defined as:
var subjectCache = [];
I then have some code to build it up, which is working ok.
However, if I try to reference the array by an index, e.g.:
var x = subjectCache[0];
or
var x = subjectCache[1];
I get undefined.
Also subjectCache.length is always 0 (zero).
if I try to reference it by its key, e.g.:
var x = subjectCache['12345'];
it works.
Is this normal? Shouldn't I be able to reference it by its index whatever?
I'm using Internet Explorer, if it makes a difference (and it probably does :( )
[Edit]
this is the code I'm using to build the array, although I really don't think it is to blame.
It's a callback from a webservice call. This is working fine and the array is being populated.
var subjectCache = [];
var subjectCacheCount = 0;
function refreshSubjectsCallback(data) {
// update subjects
// loop through retrieved subjects and add to cache
for( i=0; i < data.length; i++ )
{
var subject = data[i];
var subjectid = subject.SubjectId;
subjectCache[subjectid] = subject;
subjectCacheCount += 1;
}
}
[/Edit]
You're probably assigning keys manually instead of using subjectCache.push() to add new elements to the array:
var array = [];
array['foo'] = 'bar';
console.log(array.length); // 0
The length attribute isn't going to reflect those changes the way you'd expect:
> var a = [];
undefined
> a[100] = 2; // The previous `100` entries evaluate to `undefined`
2
> a.length;
101
Instead, use an object:
var object = {};
object['foo'] = 'bar';
for (var key in object) {
var value = object[key];
console.log(value);
}
From your symptoms, it sounds like you are trying to treat the array as an associative array.
In Javascript, arrays work like this:
var a = [];
a[1] = 10;
alert(a.length);
Objects work like this:
var o = {};
o.myProp = true;
o["myOtherProp"] = false;
Arrays only work with numeric keys not strings. Strings assign properties to the object, and aren't counted as part of length nor it's numeric indices.
When building the array, make sure you are assigning to a numeric position within the array.
No, it will not work, because you haven't created arrays but objects.
you will have to access it by its key.
var x = subjectCache['12345'];
If this works and subjectCache.length doesn't, I think you are making an object not an array. You are confused.
Somewhere along the road you lost the array, and the variable subjectCache points to a different kind of object.
If it was an array, it can't have the length zero and contain an item that is reachable using subjectCache['12345']. When you access an item in an array it doesn't make any difference if you use a numeric index or a string representing a number.

Getting Length of Object in Javascript / jQuery

I am trying to set up an array in jQuery and I then need to do a for loop on it. But it seems that I cant use an associative array for some reason?
var items = new Array();
items['foo'] = 123456;
items['bar'] = 789012;
items['baz'] = 345678;
items['bat'] = 901234;
alert(items.length);
This is just a test, but it return 0?
You can't make associative array in JavaScript like what you want, instead you can use Object.
For example:
var items = {
foo : 123456,
bar : 789012,
baz : 345678,
bat : 901234
}
And to calculate the length you can do:
var getObjectSize = function(obj) {
var len = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) len++;
}
return len;
};
Use: getObjectSize(items); // output: 4
For more see here.
Another one is:
Object.keys(items).length;
But not supported by all browsers.
var items = new Array();
items['foo'] = 123456;
The problem lies in the very first line. You believe that you are adding an item to the array at the index foo, but you are actually adding a property to the items variable with a key foo and value 123456. If you were to type items.foo it would give you back your 123456.
The problem with this approach is that adding a property to an array does not magically increase it's length.
If you want to have non-numeric indexes, you need to use an object instead of an array:
var items = {
foo: 123456,
bar: 789012,
baz: 345678,
bat: 901234
};
Another approach might be to set up two different arrays, which you construct in parallel:
var items = [], items2 = [];
items.push('foo');
items2.push(123456);
// etc.
alert(items2.length);​
The efficiency of this approach depends on how you'll use it. If you're only going to loop through the list of items and do something to each of them, this approach may be more efficient. But if you need to use it like an associative array (items['foo']), then you're better off building an object.
The .length property returns the highest numerical index of the array. Thus, in your case, there is no numerical index and it returns 0. Try
items[98] = "something";
items.length will be 98..! Use the .length property with caution, and if you also want to count the non-numerical indici, loop over the Object (an Array is also an Object) and count its ownProperties.

Categories

Resources