How to count JavaScript array objects? - javascript

When I have a JavaScript object like this:
var member = {
"mother": {
"name" : "Mary",
"age" : "48"
},
"father": {
"name" : "Bill",
"age" : "50"
},
"brother": {
"name" : "Alex",
"age" : "28"
}
}
How to count objects in this object?!
I mean how to get a counting result 3, because there're only 3 objects inside: mother, father, brother?!
If it's not an array, so how to convert it into JSON array?

That's not an array, is an object literal, you should iterate over the own properties of the object and count them, e.g.:
function objectLength(obj) {
var result = 0;
for(var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// or Object.prototype.hasOwnProperty.call(obj, prop)
result++;
}
}
return result;
}
objectLength(member); // for your example, 3
The hasOwnProperty method should be used to avoid iterating over inherited properties, e.g.
var obj = {};
typeof obj.toString; // "function"
obj.hasOwnProperty('toString'); // false, since it's inherited

You can try this code, it works perfectly in a browser:
Object.keys(member).length;

If you are using jquery on your page, this will work:
$(member).toArray().length;

You can use the Object.keys() method that returns an array of a given object's own enumerable properties:
Object.keys(member).length;

That is not an array, it is an object literal.
You can iterate the objects properties and count how many it owns:
var count = 0;
for (var k in obj) {
// if the object has this property and it isn't a property
// further up the prototype chain
if (obj.hasOwnProperty(k)) count++;
}

var member = {
"mother": {
"name" : "Mary",
"age" : "48"
},
"father": {
"name" : "Bill",
"age" : "50"
},
"brother": {
"name" : "Alex",
"age" : "28"
}
}
console.log('member key size:' + Object.keys(member).length);
ref a good guy : https://stackoverflow.com/questions/5223/length-of-a-javascript-object

Here's how I'd do it
function getObjectLength( obj )
{
var length = 0;
for ( var p in obj )
{
if ( obj.hasOwnProperty( p ) )
{
length++;
}
}
return length;
}

In my practice I work like this:
/*
* $.count(array) - Returns the number of elements in an array (immproved equivalent to .length property).
*/
$.count = function (array){
if(array.length)
return array.length;
else
{
var length = 0;
for ( var p in array ){if(array.hasOwnProperty(p)) length++;};
return length;
}
}

Related

Cleaning up a JSON object that is full of objects with 1 attribute

I have a JSON object that's formatted like the following:
{
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
}
and this format holds for dozens of attributes. I'm looking for a way to have the JSON be more like:
{
"ATTR1": "Value1",
"ATTR2": "Value2" //and so on
}
Is there an easy way to do this in Javascript? I've tried something like:
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
attr = attr[0];
}
}
But this hasn't been working. Any ideas?
Use reduce on the object's keys for that:
let foo = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
};
let res = Object.keys(foo).reduce((a,b) => {
a[b] = foo[b]['0'];
return a;
}, {});
console.log(res)
If you want to mutate the original obj, you can do this:
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
obj[attr] = obj[attr][0];
}
}
you are close!
Try something like this:
var obj = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
} //and so on
};
var obj2 = {};
for(var attr in obj) {
if(obj.hasOwnProperty(attr)) {
obj2[attr] = obj[attr][0];
}
}
alert(JSON.stringify(obj2));
Fiddle: https://jsfiddle.net/coLxfeum/
Iterating over javascript objects is easier using Object.keys(), IMO. It's supported in the major browsers... Anyway, you want to iterate over the top level object, grabbing all of it's "smallObject" values and flatten them. You can make the checks as strict as you like (insisting on "0" keys etc), but fundamentally, it seems important that the values you are collapsing are single-value objects containing string values? Anyway - here's how you could do that:
var v1 = {
"ATTR1": {
"0": "Value1"
},
"ATTR2": {
"0": "Value2"
}
}
function flatten(obj) {
Object.keys(obj).forEach( function(attr) {
var smallObj = obj[attr];
var keys = Object.keys(smallObj);
if( keys.length === 1 && typeof smallObj[keys[0]] === 'string' ) { // && keys[0] === "0" ?
obj[attr] = smallObj[keys[0]];
} // else throw Error(...) ?
})
return obj;
}
console.log(flatten(v1));
> { ATTR1: 'Value1', ATTR2: 'Value2' }
Try this :
var jsonObj = {
"ATTR1": {
"0":"Value1"
},
"ATTR2": {
"0":"Value2"
}
};
var newJson = {};
for(var i = 0;i<Object.keys(jsonObj).length;i++) {
newJson[Object.keys(jsonObj)[i]] = jsonObj[Object.keys(jsonObj)[i]]["0"];
}
console.log(newJson);

How to get Property value from a Javascript object

I have a JavaScript object.
var obj = { Id: "100", Name: "John", Address: {Id:1,Name:"Bangalore"} }
var dataToRetrieve= "Name";
function GetPropertyValue(object,dataToRetrieve){
return obj[dataToRetrieve]
}
var retval = GetPropertyValue(obj,dataToRetrieve)
This works fine. But if I try to get the value of property value of "Address.Name" ,
Like : var dataToRetrieve = "Address.Name";
it shows undefined.
Note : The property variable is set by user from HTML And it can be changed according to user requirement(which property value he wants).
What I want to achieve :
1) If dataToRetrieve = "Name" , it should give me "John",
2) If dataToRetrieve = "Id" , it should give me "100",
3) If dataToRetrieve = "Address.Name" , it should give me "Bangalore",
4) If dataToRetrieve = "Address.Id" , it should give me 1
Plunkr Here : PLUNKR
Use reduce() method
var obj = {
Id: "100",
Name: "John",
Address: {
Id: 1,
Name: "Bangalore"
}
}
function GetPropertyValue(obj1, dataToRetrieve) {
return dataToRetrieve
.split('.') // split string based on `.`
.reduce(function(o, k) {
return o && o[k]; // get inner property if `o` is defined else get `o` and return
}, obj1) // set initial value as object
}
console.log(
GetPropertyValue(obj, "Name"),
GetPropertyValue(obj, "Id"),
GetPropertyValue(obj, "Address.Name"),
GetPropertyValue(obj, "Address.Id"),
GetPropertyValue(obj, "Address.Idsd"),
GetPropertyValue(obj, "Addre.Idsd")
)
For older browser check polyfill option of reduce method.
Use following function:
var obj = { Id: "100", Name: "John",
Address: [{ Id:1, Name:"Bangalore" }, { Id:2, Name: "Mysore" } ] };
function GetPropertyValue(object, dataToRetrieve) {
dataToRetrieve.split('.').forEach(function(token) {
if (object) object = object[token];
});
return object;
}
console.log(
GetPropertyValue(obj, "Address.0.Name"),
GetPropertyValue(obj, "Address.1.Id"),
GetPropertyValue(obj, "Name"),
GetPropertyValue(obj, "Id"),
GetPropertyValue(obj, "Unknown"),
GetPropertyValue(obj, "Some.Unknown.Property")
);
function GetPropertyValue(object,dataToRetrieve){
var valueArray = dataToRetrieve.split(".");
if (valueArray.length <= 1) {
return object[valueArray];
} else {
var res;
function browseObj(obj, valueArray, i) {
if (i == valueArray.length)
res = obj;
else
browseObj(obj[valueArray[i]], valueArray, i+1);
}
browseObj(object, valueArray, 0);
return res;
}
}
I had written a standard reusable Object method to access nested properties dynamically. It's like
Object.prototype.getNestedValue = function(...a) {
return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
It will take dynamic arguments for the nested properties. If they are string type they are object properties if number type then they are array indices. Once you have this, your job becomes very easy. Let's see..
Object.prototype.getNestedValue = function(...a) {
return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
var props = ["Address","Name"],
obj = { Id: "100", Name: "John", Address: {Id:1,Name:"Bangalore"} },
val = obj.getNestedValue(...props);
console.log(val);
// or you can of course do statically like
val = obj.getNestedValue("Address","Name");
console.log(val);
You can see getNestedValue() and it's twin setNestedValue() working at https://stackoverflow.com/a/37331868/4543207

How to sort an array of objects by one of the objects string values numerically?

I have an array of objects similar to this :
var this array = [
{
"id" : "A20",
"age" : "16"
},
{
"id" : "A2",
"age" : "12"
},
{
"id" : "B16",
"age" : "45"
}]
I need to sort this array by their ID, So it would end up like :
this array = [
{
"id" : "A2",
"age" : "12"
},
{
"id" : "A20",
"age" : "16"
},
{
"id" : "B16",
"age" : "45"
}]
I have this method of sorting :
nodes.sort(function(a,b){
// console.log(a.Pos)
// console.log(a.pinNum)
var alc = a.id, blc = b.id;
console.log(alc)
return alc > blc ? 1 : alc < blc ? -1 : 0;
});
But this only works alphabetically. I have also found this but it gives back just the strings I pass to the function not the array of objects :
function sortArray(arr) {
var tempArr = [],
n;
console.log(arr)
for (var i in arr) {
var thisString = arr[i].id;
// tempArr[i] = arr[i].match(/([^0-9]+)|([0-9]+)/g);
tempArr[i] = thisString.match(/([^0-9]+)|([0-9]+)/g);
for (var j in tempArr[i]) {
if (!isNaN(n = parseInt(tempArr[i][j]))) {
tempArr[i][j] = n;
}
}
}
tempArr.sort(function (x, y) {
for (var i in x) {
if (y.length < i || x[i] < y[i]) {
return -1; // x is longer
}
if (x[i] > y[i]) {
return 1;
}
}
return 0;
});
for (var i in tempArr) {
arr[i] = tempArr[i].join('');
}
return arr;
}
console.log(sortArray(nodes).join(","));
What I need is the second sorting function but with the ability to sort both alphabetically and numerically. Thanks
var array = [{
"id" : "A20",
"age" : "16"
}, {
"id" : "A2",
"age" : "12"
}, {
"id" : "B16",
"age" : "45"
}];
array.sort(function(a, b) {
var aSplit = /(\D*)(\d*)/.exec(a.id),
bSplit = /(\D*)(\d*)/.exec(b.id);
if( aSplit[1] !== bSplit[1] )
return aSplit[1].localeCompare(bSplit[1]);
else
return aSplit[2] - bSplit[2];
});
Use function .sort in array, and pass has argument, a callback.
This callback receive elements to iterate, and you can compare values, if return true, switch order of elements, for i.e:
arr.sort(function(a, b) {
return parseInt(a.age) > parseInt(b.age))
};
or, if you use ecma script 6, you can use arrow function, is better, i.e. below:
arr.sort((a, b) => parseInt(a.age) > parseInt(b.age))
Docs here:
http://www.w3schools.com/jsref/jsref_sort.asp
I think you can use localeCompare() to compare strings. Try this code, it should work:
nodes.sort(function(a,b){
// console.log(a.Pos)
// console.log(a.pinNum)
var alc = a.id, blc = b.id;
console.log(alc)
return alc.localeCompare(blc);
});

Get an object in array by one of its fields

Sorry I'm kind of new to JS; I have an array of object; how can I get the name of the object which has the key "user_key3" and obviously without having a loop and have a condition.
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}]
Please let me know if you need more clarification
Thanks
You can do it the functional way, like this
var name;
arr.forEach(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
}
});
If you want to short-circuit on the first match, you can use Array.prototype.some, like this
var name;
arr.some(function(currentObject) {
if (currentObject.key === "user_key3") {
name = currentObject.name;
return true;
}
return false;
});
The OP had mentioned obviously without having a loop and have a condition. I would do it as below:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
var keyValMap = arr.map(function(n) { return n.key } );
var arrIndex = keyValMap.indexOf('user_key3');
alert(arr[arrIndex].name);
Fiddle
You'll have to iterate and check for the key
var user_name;
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === 'user_key3' ) {
user_name = arr[i].name;
break;
}
}
FIDDLE
You've edited the question to include
obviously without having a loop and have a condition
but a loop and a condition is by far the most efficient and cross-browser way to do this, so why would you "obviously" not want this ?
An inefficient yet concise solution would be
var keyarr = arr.map(function(x) { return x.key } );
//keyarr is list of keys
var index=keyarr.indexOf("user_key3");
//arr[index] is your answer. Index will be -1 if the key doesn't exist
In general, finding an item that satisfies some arbitrary property in an array requires you to loop over the array:
function find(arr, name) {
for (var i=0; i<arr.length; i++) {
if ( arr[i].key === name ) {
return arr[i];
}
}
}
Then to find it,
var obj = find(arr, 'user_key3');
Using more functional solutions to find the item is fine too, but you still end up looping in some way.
However, if you are doing lookups by key, then an array of key-value pairs is not the best data structure. I would suggest using an object directly:
var map = {
'user_key1': 'user1',
'user_key2': 'user2',
'user_key3': 'user3'
}
Then lookup is simply:
map['user_key3'];
Try this - underscore.js
For Your Example -
_.where(arr, {key: "user_key3"});
You cannot do such thing with Objects in Javascript. Though here you have a combination of callbacks and loop:
arr = [{
"name": "user1",
"key": "user_key1"
},{
"name": "user3",
"key": "user_key3"
},{
"name": "user2",
"key": "user_key2"
}];
arr.forEach(function(elme){
for(var g in elme)
{
if(elme[g] == 'user_key3')
{
console.log("Found the value: "+g+" : "+elme[g]);
};
}
});

how to construct a json object using info from several javascript arrays

I have two js arrays already, say: names and values (with the same length), now I would like to construct a json object in certain format? For example:
names = ["label1","label2","label3"];
values = [[[0,1],[1,9],[2,10]],[[0,89],[1,91],[2,1]],[[0,1],[1,9],[2,10]]];
I would like to have a json array data_spec in this format:
[{
label:"label1",
data:[[0,1],[1,9],[2,10]]
},
{
label:"label2",
data:[[0,89],[1,91],[2,1]]
},
{
label:"label3",
data:[[0,1],[1,9],[2,10]]
}]
Could anyone tell one how? Thanks a lot!
For a bit of variety and a check,
var data_spec = [];
if (names.length != values.length) {
// panic, throw an exception, log an error or just return an empty array
} else {
for (var i=0, name; name = names[i]; i++) { // assuming a non-sparse array
data_spec[i] = {
label : name,
data : values[i]
};
}
}
That is, non-sparse and not containing anything else that would evaluate to false.
If your framework has an each function added to Array and you don't care about performance,
var data_spec = [];
names.each(function(name) {
data_spec.push({ label : name, data : values[names.indexOf(name)] });
});
If your framework is a clean one like Dojo and puts it somewhere else (ex is Dojo),
var data_spec = [];
dojo.forEach(names, function(name) {
data_spec.push({ label : name, data : values[names.indexOf(name)] });
});
If your framework has an each function that returns an Array of identical length with the results of every operation at their expected position,
var data_spec = arrayOfResultsEach(names, function(name) {
return { label : name, data : values[names.indexOf(name)] };
});
These are just for illustration, indexOf inside loops of arbitrary length is a major code smell.
Just use a loop (make sure the two arrays are of same length)
result = [];
for(var i=0, len=names.length; i < len; i++) {
result.push({label: names[i], data: values[i]});
}
var myArray =
[{
"label": "label1",
"data" :
{
"0": "1",
"1": "9",
"2": "10"
}
},
{
"label": "label2",
"data" :
{
"0": "89",
"1": "91",
"2": "1"
}
},
{
"label": "label3",
"data" :
{
"0": "1",
"1": "9",
"2": "10"
}
}];
alert(myArray[0].data[2]);

Categories