Retrieving Keys from JSON Array key-value pair dynamically - Javascript - javascript

I have a question that would like to seek your expertise on.
This is a JSON array that I have:
[{"A":20,"B":32,"C":27,"D":30,"E":40}]
What I would like to do is to retrieve the keys (A, B, C, D, E) from the JSON array instead of the values. I am able to retrieve the values but not the keys.
I am using this to retrieve the values dynamically:
function calculateSum(jsonArray) {
var result = 0;
for (var i = jsonArray.length - 1; i >= 0; --i)
{
var o = jsonArray[i];
A = o.A;
B = o.B;
C = o.C;
D = o.D;
E = o.E;
result = A + B + C + D + E;
return result;
}
return result;
}
Similarly, what should I do to retrieve the keys using JavaScript?

Are you using D3.js as your tag implies? Because in that case, you can just use d3.keys():
var data = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
d3.keys(data[0]); // ["A", "B", "C", "D", "E"]
If you want the sum of all the values, you might be better off using d3.values() and d3.sum():
var data = [{"A":20,"B":32,"C":27,"D":30,"E":40}, {"F":50}];
// get total of all object totals
var total = d3.sum(data, function(d) {
// get total of a single object's values
return d3.sum(d3.values(d));
});
total; // 199

All of the current posted solutions have a problem. None of them check for object.hasOwnProperty(prop) while iterating over an object using a for...in loop. This might cause phantom keys to appear if properties are added to the prototype.
Quoting Douglas Crockford
Be aware that members that are added to the prototype of the object will be included in the enumeration. It is wise to program defensively by using the hasOwnProperty method to distinguish the true members of the object.
Adding a check for hasOwnProperty to maerics' excellent solution.
var getKeys = function (arr) {
var key, keys = [];
for (i = 0; i < arr.length; i++) {
for (key in arr[i]) {
if (arr[i].hasOwnProperty(key)) {
keys.push(key);
}
}
}
return keys;
};

Use for .. in:
var result = 0;
for (var i = jsonArray.length - 1; i >= 0; --i) {
var o = jsonArray[i];
for (var key in o) {
if (o.hasOwnProperty(key)) {
result += o[key];
}
}
// in your code, you return result here,
// which might not give the right result
// if the array has more than 1 element
}
return result;

var easy = {
a: 1,
b: 2,
c: 3
}
var keys = [], vals = []
for (var key in easy) {
keys.push(key)
vals.push(easy[key])
}
alert(keys+" - tha's how easy baby, it's gonna be")
alert(vals+" - tha's how easy baby, it's gonna be")
defensively
Including #Sahil's defensive method...
for (var key in easy) {
if (easy.hasOwnProperty(key)) {
keys.push(key)
vals.push(easy[key])
}
}

Try using the JavaScript for..in statement:
var getKeys = function(arr) {
var key, keys = [];
for (i=0; i<arr.length; i++) {
for (key in arr[i]) {
keys.push(key);
}
}
return keys;
};
var a = [{"A":20, "B":32, "C":27, "D":30, "E":40}, {"F":50}]
getKeys(a); // => ["A", "B", "C", "D", "E", "F"]

I think this is the simplest.
var a = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
Object.keys( a[0] );
Result :
["A", "B", "C", "D", "E"]

A for-in-loop does the trick. On one object it looks like this:
var o = {
a: 5,
b: 3
};
var num = 0;
for (var key in o) {
num += o[key];
}
alert(num);

Try this. It is simple:
var a = [{"A":20,"B":32,"C":27,"D":30,"E":40}];
for(var i in a){
for(var j in a[i]){
console.log(j); // shows key
console.log(a[i][j]); // shows value
}
}

I think this should be parsed recursively like below
var getKeys = function(previousKeys,obj){
var currentKeys = Object.keys(obj);
previousKeys = previousKeys.concat(currentKeys);
for(var i=0;i<currentKeys.length;i++){
var innerObj = obj[currentKeys[i]];
if(innerObj!==null && typeof innerObj === 'object' && !Array.isArray(innerObj)){
return this.getKeys(previousKeys,innerObj);
}
}
return previousKeys;
}
usage: getKeys([],{"a":"1",n:{c:"3",e:{ f:4,g:[1,2,3]}}})
Result:
["a", "n", "c", "e", "f", "g"]

var _ = require('underscore');
var obj = [{"A":20,"B":32,"C":27,"D":30,"E":40},{"F":50}, {"G":60,"H":70},{"I":80}];
var keys = [], values = [];
_.each(obj, function(d) {
keys.push(_.keys(d));
values.push(_.values(d));
});
// Keys -> [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' ]
console.log('Keys -> ', _.flatten(keys ));
// Values -> [ 20, 32, 27, 30, 40, 50, 60, 70, 80 ]
console.log('Values -> ', _.flatten(values));

stop reinventing the wheel !
Object.keys()
MDN

Related

JavaScript - get arrays of indexes of same value in the original array

I have an array. For example
var tmp = ["A", "B","B", "A", "B", "B", "A", "A"];
how can I get array of index for each possible value from array above using plain JavaScript.
var A = [0,3,6,7]; //0,3,6,7 are indexes of "A" from the above array
var B = [1,2,4,5]; //1,2,4,5 are indexes of "B" from the above array
Thank you.
Iterate and push the index to the corresponding array.
var A = [],
B = [];
var tmp = ["A", "B", "B", "A", "B", "B", "A", "A"];
tmp.forEach(function(v, i) {
if (v == 'A') A.push(i);
else B.push(i);
})
console.log(A, B);
You can try something like this:
Logic
Instead of creating individual variable for A and B, you can create map which will hold these values as keys.
Now loop over array and add index to necessary array.
Note: Benefit of using a map is that your logic becomes generic and it will be scalable. So it you add 5 more letters, you dont have to create 5 more variables and update logic
var tmp = ["A", "B", "B", "A", "B", "B", "A", "A"];
var result = tmp.reduce(function(acc, item, i) {
acc[item] = acc[item] || [];
acc[item].push(i);
return acc;
}, {})
console.log(result)
x = {};
for(var i=0;i<tmp.length;i++)
{
if(!x[tmp[i]])
x[tmp[i]] = [];
x[tmp[i]].push(i);
}
//x['A'] and x['B'] contains what you're looking for.
To find occurrence of each element
var tmp = ["A", "B","B", "A", "B", "B", "A", "A"];
var arr = [];
var temp = [];
for(let i in tmp){
var indexes = [];
if(temp.indexOf(tmp[i]) === -1){
indexes = tmp.map((e, j) => e === tmp[i] ? j : '').filter(String);
var obj = {};
obj[tmp[i]] = indexes;
arr.push(obj);
temp.push(tmp[i]);
}
}
console.log(arr);
var tmp = ["A", "B","B", "A", "B", "B", "A", "A"];
var arr = [];
var temp = [];
for(let i in tmp){
var indexes = [];
if(temp.indexOf(tmp[i]) === -1){
indexes = tmp.map((e, j) => e === tmp[i] ? j : '').filter(String);
temp.push(tmp[i]);
window[tmp[i]] = indexes;
}
}
console.log(A);
console.log(B);

Count instances of string in a very large array and add the value to a hash value

I have a very large array of words in an array, and I want to count all of them and add the count as a value to each string.
So I for example:
words = ["a", "hello", "hello", "b", "went", "a"]
I want to convert this into:
words = [{"a" => 2}, {"b" => 1}, {"hello" => 2}, {"went" => 1}]
I have seen ways to simply count one word in a string and return its occurrences, but how might I do this at a large scale, while creating an array of hashes with the number of occurrences?
I can remove duplicate values after, I am more interested in the process of counting the values and adding the count as values in a hash.
In first turn you can create an object with the array value and number of occurrence.Then loop through it to create an array of objects
var words = ["a", "hello", "hello", "b", "went", "a"];
var rObj = {};
var finalArray = [];
words.map(function(currentValue, index) {
if (rObj.hasOwnProperty(currentValue)) {
rObj[currentValue] = rObj[currentValue] + 1;
} else {
rObj[currentValue] = 1
}
});
for (var keys in rObj) {
var obj = {};
obj[keys] = rObj[keys];
finalArray.push(obj)
};
console.log(finalArray)
You can first use reduce() to count elements and return object and then map() to return array of object values.
var words = ["a", "hello", "hello", "b", "went", "a"]
var count = words.reduce(function(r, e) {
if(!r[e]) r[e] = {[e]: 1}
else r[e][e] += 1
return r;
}, {})
var result = Object.keys(count).map(e => count[e])
console.log(result)
For a really huge array, I suggest to use either a while of a for loop and a plain check if the key with the word exist. If not assign zero to it. Later increment the property of the count object.
At last convert the object into an array with the wanted structure.
var words = ["a", "hello", "hello", "b", "went", "a"],
w,
i = words.length,
count = Object.create(null),
result;
while (i--) {
w = words[i];
if (!count[w]) {
count[w] = 0;
}
count[w]++;
}
result = Object.keys(count).map(function (k) {
var temp = {};
temp[k] = count[k];
return temp;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Don't count repeaters by hashing. Use a while loop for smaller overhead. Assignments over calculation. You will get an answer on orders of magnitude 5 times faster. One million words randomly generated from 12 words in a 1/5th of the time.
var wordsArray = ['apple', 'beer', 'cake', 'potato', 'orange', 'monitor', 'program', 'application', 'keyboard', 'javascript', 'gaming', 'network'],
words = [];
for (i = 0; i < 1000000; i++) {
words.push(wordsArray[Math.floor(Math.random() * wordsArray.length)]);
}
function getCount(words) {
var w,
i = words.length,
hash = {};
while (i--) {
w = words[i];
if (!hash[w]) {
hash[w] = 0;
}
hash[w]++;
}
return hash
}
console.time('Obj-time');
var counts = getCount(words);
array = [];
for (let i in counts) {
var l = i.length,
val = counts[i];
array.push({
[i]: val * l
})
}
console.log(array);
console.timeEnd('Obj-time');

How to remove keys for list of objects in javascript [duplicate]

My application creates a JavaScript object, like the following:
myObj= {1:[Array-Data], 2:[Array-Data]}
But I need this object as an array.
array[1]:[Array-Data]
array[2]:[Array-Data]
So I tried to convert this object to an array by iterating with $.each through the object and adding the element to an array:
x=[]
$.each(myObj, function(i,n) {
x.push(n);});
Is there an better way to convert an object to an array or maybe a function?
If you are looking for a functional approach:
var obj = {1: 11, 2: 22};
var arr = Object.keys(obj).map(function (key) { return obj[key]; });
Results in:
[11, 22]
The same with an ES6 arrow function:
Object.keys(obj).map(key => obj[key])
With ES7 you will be able to use Object.values instead (more information):
var arr = Object.values(obj);
Or if you are already using Underscore/Lo-Dash:
var arr = _.values(obj)
var myObj = {
1: [1, 2, 3],
2: [4, 5, 6]
};
var array = $.map(myObj, function(value, index) {
return [value];
});
console.log(array);
Output:
[[1, 2, 3], [4, 5, 6]]
Simply do
Object.values(obj);
That's all!
I think you can use for in but checking if the property is not inerithed
myObj= {1:[Array-Data], 2:[Array-Data]}
var arr =[];
for( var i in myObj ) {
if (myObj.hasOwnProperty(i)){
arr.push(myObj[i]);
}
}
EDIT - if you want you could also keep the indexes of your object, but you have to check if they are numeric (and you get undefined values for missing indexes:
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
myObj= {1:[1,2], 2:[3,4]}
var arr =[];
for( var i in myObj ) {
if (myObj.hasOwnProperty(i)){
if (isNumber(i)){
arr[i] = myObj[i];
}else{
arr.push(myObj[i]);
}
}
}
If you know the maximum index in you object you can do the following:
var myObj = {
1: ['c', 'd'],
2: ['a', 'b']
},
myArr;
myObj.length = 3; //max index + 1
myArr = Array.prototype.slice.apply(myObj);
console.log(myArr); //[undefined, ['c', 'd'], ['a', 'b']]
Since ES5 Object.keys() returns an array containing the properties defined directly on an object (excluding properties defined in the prototype chain):
Object.keys(yourObject).map(function(key){ return yourObject[key] });
ES6 takes it one step further with arrow functions:
Object.keys(yourObject).map(key => yourObject[key]);
Nowadays, there is a simple way to do this : Object.values().
var myObj = {
1: [1, 2, 3],
2: [4, 5, 6]
};
console.log(Object.values(myObj));
Output:
[[1, 2, 3], [4, 5, 6]]
This doesn't required jQuery, it's been defined in ECMAScript 2017.
It's supported by every modern browser (forget IE).
The best method would be using a javascript -only function:
var myArr = Array.prototype.slice.call(myObj, 0);
x = [];
for( var i in myObj ) {
x[i] = myObj[i];
}
ECMASCRIPT 5:
Object.keys(myObj).map(function(x) { return myObj[x]; })
ECMASCRIPT 2015 or ES6:
Object.keys(myObj).map(x => myObj[x])
How about jQuery.makeArray(obj)
This is how I did it in my app.
ES8 way made easy:
The official documentation
const obj = { x: 'xxx', y: 1 };
let arr = Object.values(obj); // ['xxx', 1]
console.log(arr);
The solving is very simple
var my_obj = {1:[Array-Data], 2:[Array-Data]}
Object.keys(my_obj).map(function(property_name){
return my_obj[property_name];
});
Fiddle Demo
Extension to answer of bjornd .
var myObj = {
1: [1, [2], 3],
2: [4, 5, [6]]
}, count = 0,
i;
//count the JavaScript object length supporting IE < 9 also
for (i in myObj) {
if (myObj.hasOwnProperty(i)) {
count++;
}
}
//count = Object.keys(myObj).length;// but not support IE < 9
myObj.length = count + 1; //max index + 1
myArr = Array.prototype.slice.apply(myObj);
console.log(myArr);
Reference
Array.prototype.slice()
Function.prototype.apply()
Object.prototype.hasOwnProperty()
Object.keys()
If you want to keep the name of the object's properties as values. Example:
var fields = {
Name: { type: 'string', maxLength: 50 },
Age: { type: 'number', minValue: 0 }
}
Use Object.keys(), Array.map() and Object.assign():
var columns = Object.keys( fields ).map( p => Object.assign( fields[p], {field:p} ) )
Result:
[ { field: 'Name', type: 'string', maxLength: 50 },
{ field: 'Age', type: 'number', minValue: 0 } ]
Explanation:
Object.keys() enumerates all the properties of the source ; .map() applies the => function to each property and returns an Array ; Object.assign() merges name and value for each property.
I made a custom function:
Object.prototype.toArray=function(){
var arr=new Array();
for( var i in this ) {
if (this.hasOwnProperty(i)){
arr.push(this[i]);
}
}
return arr;
};
After some tests, here is a general object to array function convertor:
You have the object:
var obj = {
some_key_1: "some_value_1"
some_key_2: "some_value_2"
};
The function:
function ObjectToArray(o)
{
var k = Object.getOwnPropertyNames(o);
var v = Object.values(o);
var c = function(l)
{
this.k = [];
this.v = [];
this.length = l;
};
var r = new c(k.length);
for (var i = 0; i < k.length; i++)
{
r.k[i] = k[i];
r.v[i] = v[i];
}
return r;
}
Function Use:
var arr = ObjectToArray(obj);
You Get:
arr {
key: [
"some_key_1",
"some_key_2"
],
value: [
"some_value_1",
"some_value_2"
],
length: 2
}
So then you can reach all keys & values like:
for (var i = 0; i < arr.length; i++)
{
console.log(arr.key[i] + " = " + arr.value[i]);
}
Result in console:
some_key_1 = some_value_1
some_key_2 = some_value_2
Edit:
Or in prototype form:
Object.prototype.objectToArray = function()
{
if (
typeof this != 'object' ||
typeof this.length != "undefined"
) {
return false;
}
var k = Object.getOwnPropertyNames(this);
var v = Object.values(this);
var c = function(l)
{
this.k = [];
this.v = [];
this.length = l;
};
var r = new c(k.length);
for (var i = 0; i < k.length; i++)
{
r.k[i] = k[i];
r.v[i] = v[i];
}
return r;
};
And then use like:
console.log(obj.objectToArray);
You can create a simple function to do the conversion from object to array, something like this can do the job for you using pure javascript:
var objectToArray = function(obj) {
var arr = [];
if ('object' !== typeof obj || 'undefined' === typeof obj || Array.isArray(obj)) {
return obj;
} else {
Object.keys(obj).map(x=>arr.push(obj[x]));
}
return arr;
};
or this one:
var objectToArray = function(obj) {
var arr =[];
for(let o in obj) {
if (obj.hasOwnProperty(o)) {
arr.push(obj[o]);
}
}
return arr;
};
and call and use the function as below:
var obj = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'};
objectToArray(obj); // return ["a", "b", "c", "d", "e"]
Also in the future we will have something called Object.values(obj), similar to Object.keys(obj) which will return all properties for you as an array, but not supported in many browsers yet...

Modify an object to a new Array in Javascript

sorry, i m a beginner in javascript.
Can someone explain me how to modify this Object
{toto:[12,13,15],titi:[45,12,34]}
to this Array
newArray = [
{
toto:12,
titi:45
},{
toto:13,
titi:12
},{
toto:15,
titi:34}
]
Also, what the solution if the toto and titi doesn't have the same lenght
Thanks for support!
Here's how I did it. In this way, you don't need to know the names of the keys or the size of the array, but it does require a few loops.
obj = {toto:[12,13,15],titi:[45,12,34]};
newArray = [];
// Find the longest array in your data set
longest = 0;
Object.keys(obj).forEach(function(key) {
if (obj[key].length > longest) {
longest = obj[key].length;
}
});
// Loop through the existing data set to create new objects
for (i = 0; i<longest; i++) {
newObject = {};
Object.keys(obj).forEach(function(key) {
newObject[key] = obj[key][i];
});
newArray.push(newObject);
}
console.log(newArray);
plnkr.co demo in the script.js file.
If you want to ignore keys that would have undefined values for uneven loops, you can add a conditional inside the forEach loop that creates a new object:
Object.keys(obj).forEach(function(key) {
if (obj[key][i] !== undefined) {
newObject[key] = obj[key][i];
}
});
Assuming lengths of toto and titi are the same:
Obj = {toto:[12,13,15],titi:[45,12,34]};
newArray = [];
for (var k in Obj["toto"]) {
newArray.push({ toto:Obj["toto"][k],titi:Obj["titi"][k] });
}
Since the lengths of your inner arrays are equal, you should be able to simply loop through them and add a value from each array (for each iteration) into a new array :
// Your input
var input = {toto:[12,13,15],titi:[45,12,34]};
// An array to store your output
var output = [];
// Since your inner arrays are of equal size, you can loop through them
// as follows
for(var i = 0; i < input.toto.length; i++){
output.push({ toto: input.toto[i], titi: input.titi[i]});
}
You can see a working example of this here and what the output array looks like below :
A more generic approach
var object = { toto: [12, 13, 15], titi: [45, 12, 34] },
newArray = function (o) {
var keys = Object.keys(o),
l = keys.reduce(function (r, a) { return Math.max(r, o[a].length); }, 0),
i = 0,
t,
result = [];
while (i < l) {
t = {};
keys.forEach(function (k) { t[k] = o[k][i]; });
result.push(t);
i++;
}
return result;
}(object);
document.write('<pre>' + JSON.stringify(newArray, 0, 4) + '</pre>');

Javascript algorithm to find elements in array that are not in another array

I'm looking for a good algorithm to get all the elements in one array that are not elements in another array. So given these arrays:
var x = ["a","b","c","t"];
var ​​​​​​​​​y = [​​​​​​​"d","a","t","e","g"];
I want to end up with this array:
var z = ["d","e","g"];
I'm using jquery, so I can take advantage of $.each() and $.inArray(). Here's the solution I've come up with, but it seems like there should be a better way.
// goal is to get rid of values in y if they exist in x
var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];
var z = [];
$.each(y, function(idx, value){
if ($.inArray(value,x) == -1) {
z.push(value);
}
});
​alert(z); // should be ["d","e","g"]
Here is the code in action. Any ideas?
in ES6 simply
const a1 = ["a", "b", "c", "t"];
const a2 = ["d", "a", "t", "e", "g"];
console.log( a2.filter(x => !a1.includes(x)) );
(another option is a2.filter(x => a1.indexOf(x)===-1) )
Late answer with the new ECMA5 javascript:
var x = ["a","b","c","t"];
var y = ["d","a","t","e","g"];
myArray = y.filter( function( el ) {
return x.indexOf( el ) < 0;
});
var z = $.grep(y, function(el){return $.inArray(el, x) == -1});
Also, that method name is too short for its own good. I would expect it to mean isElementInArray, not indexOf.
For a demo with objects, see http://jsfiddle.net/xBDz3/6/
Here's an alternative using underscore.js:
function inAButNotInB(A, B) {
return _.filter(A, function (a) {
return !_.contains(B, a);
});
}
I am quite late now but maybe it will be helpful for someone.
If the array is not just a simple array but an array of objects then the following can be used:
var arr1 = [
{
"prop1": "value1",
"prop2": "value2",
},
{
"prop1": "value3",
"prop2": "value4",
},
{
"prop1": "value5",
"prop2": "value6",
},
];
var arr2 = ['value1','value3', 'newValue'];
// finds all the elements of arr2 that are not in arr1
arr2.filter(
val => !arr1.find( arr1Obj => arr1Obj.prop1 === val)
); // outputs "newValue"
This is a late answer, but it uses no libraries so some may find it helpful.
/**
* Returns a non-destructive Array of elements that are not found in
* any of the parameter arrays.
*
* #param {...Array} var_args Arrays to compare.
*/
Array.prototype.uniqueFrom = function() {
if (!arguments.length)
return [];
var a1 = this.slice(0); // Start with a copy
for (var n=0; n < arguments.length; n++) {
var a2 = arguments[n];
if (!(a2 instanceof Array))
throw new TypeError( 'argument ['+n+'] must be Array' );
for(var i=0; i<a2.length; i++) {
var index = a1.indexOf(a2[i]);
if (index > -1) {
a1.splice(index, 1);
}
}
}
return a1;
}
Example:
var sheetUsers = ['joe#example.com','fred#example.com','sam#example.com'];
var siteViewers = ['joe#example.com','fred#example.com','lucy#example.com'];
var viewersToAdd = sheetUsers.uniqueFrom(siteViewers); // [sam#example.com]
var viewersToRemove = siteViewers.uniqueFrom(sheetUsers); // [lucy#example.com]
findDiff = (A, B) => {
return A.filter(function (a) {
return !B.includes(a);
});
}
Make sorted copies of the arrays first. If the top elements are equal, remove them both. Otherwise remove the element that is less and add it to your result array. If one array is empty, then add the rest of the other array to the result and finish. You can iterate through the sorted arrays instead of removing elements.
// assume x and y are sorted
xi = 0; yi = 0; xc = x.length; yc = y.length;
while ( xi < xc && yi < yc ) {
if ( x[xi] == y[yi] ) {
xi += 1;
yi += 1;
} else if ( x[xi] < y[yi] ) {
z.push( x[xi] );
xi += 1;
} else {
z.push( y[yi] );
yi += 1;
}
}
// add remainder of x and y to z. one or both will be empty.
Maybe jLinq can help you?
It lets you run queries like this against javascript objects.
For example:
var users = [ { name: "jacob", age: 25 }, { name: "bob" , age: 30 }]
var additionalusers = [ { name: "jacob", age: 25 }, { name: "bill" , age: 25 }]
var newusers = jLinq.from(users).except(additionalusers).select();
>>> newusers = [ { name: "bob" , age: 30 } ]
It's a bit overkill for you at the moment, but it's a robust solution that I was glad to learn about.
It can do intersects, unions, handle boolean logic and all kinds of great linq style goodness.

Categories

Resources