Re-ordering JSON data from jQuery .getJSON() - javascript

I'm using $.getJSON to pull some data from an data source and the result comes in as JSON, but it's in this format (as it comes from a table):
result {
0: Array {
0: 'First Name',
1: 'Last Name',
2: 'City',
3: 'State'
}
1: Array {
0: 'John',
1: 'Doe',
2: 'Portland',
3: 'Oregon'
}
2: Array {
0: 'Jane',
1: 'Doe',
2: 'Seattle',
3: 'Washington'
}
}
I need to get that data into something that looks more like this:
Object {
'First Name': 'John', 'Jane'
'Last Name': 'Doe', 'Doe'
'City': 'Portland', 'Seattle'
'State': 'Oregon', 'Washington'
}
I thought that I would just put these into a few $.each() loops but I can't seem to get an object with the first array's values as the keys and the matching values as items in an array assigned to that key. I've tried something like this:
var tmpArray = [];
var labelKeys = [];
$.each(result, function(key, val){
if (key < 1){
$.each(val, function(labelKey, labelVal){
labelKeys.push(labelVal);
}
} else {
for (var i=0; i<labelKeys.length;i++){
tmpArray[labelKeys[i]].push(val[i]);
}
}
}
That doesn't work and I get an undefined error for push().
I can separate all the arrays out into their own arrays and get them out to the console, but I can't figure out how to push data to an object or an array using a key value.
How do I push values to an object so that I can just loop through the arrays and group the objects at the same numbered location and assign it to a key that's at the same location in the first array?

You can't call .push() on tmpArray[labelKeys[i]] because it doesn't exist yet. You need to add that key to the object, before trying to call .push().
// this needs to be an object
// arrays can only have numeric keys
var tmpArray = {};
var labelKeys = [];
$.each(result, function(key, val){
if (key < 1){
$.each(val, function(labelKey, labelVal){
labelKeys.push(labelVal);
// Create an array for this label
tmpArray[labelVal] = [];
});
} else {
for (var i=0; i<labelKeys.length;i++){
tmpArray[labelKeys[i]].push(val[i]);
}
}
});

Related

Create a subset of data selected on columns in 2d javascript array

Sorry for the basic question and bad lexicon, I am (very) new to javascript. I have an array of data and I would like to create a subset of that data, based on selected columns. The first few rows of my data, for example:
0: {ID: 3607, Name: 'Alamo', Funds: 52933955,
Revenues: 9160109, BAT: 5, …}
1: {ID: 3539, Name: 'Alvin', Funds: 6128147,
Revenues: 964083, BAT: 0, …}
2: {ID: 3540, Name: 'Amarillo', Funds: 12450969,
Revenues: 1716038, BAT: 0, …}
I want to create a new array from columns 0, 1, 2, and 4 (ID, Name, Funds, and BAT). In the code below, toolData is the array created from the original dataset (toolData.json), and tableData is the array I'm trying to create from the selected data. selections contains the column numbers I want to pull into the new array.
var getData = () => axios.get('toolData.json')
.then(res => res.data)
.then(data => {
var toolData = data;
console.log(toolData);
var tableData = [];
var selections = [0,1,2,4];
for (i=0; i < toolData.length; i++)
{
tableData[i] = toolData[i];
for (j=0; selections.length; j++)
{
k = selections[j],
tableData[i][j] = toolData[i][k]
}
}
console.log(tableData);
This particular code snippet doesn't work at all, I'm assuming I've created an infinite loop somehow. If I comment out tableData[i] = toolData[i]; then that problem resolves, but the code still doesn't work. console.log(toolData); gives me what I'm looking for (the full panel of data), but console.log(tableData); gives the error:
javascript.js:42 Uncaught (in promise) TypeError: Cannot set properties of undefined (setting '0')
at javascript.js:42
Ultimately I would like the user to be able to choose the columns they want to include in the new array, but before I can figure that puzzle out I need to solve this one.
Well, it seems from what you're saying is that every index in the array is an object.. arr[0][0]==undefined but arr[0]['ID']==3607
function newSubset(arr,dataToSelect){
//arr is the fetched array, dataToSelect is an array of the keys(like ID,Name...) that you want from the array
return arr.map(obj=>{
var toReturn={} //object that would give each desired key for each part in arr
dataToSelect.forEach(key=>toReturn[key]=obj[key]) //placing wanted keys in toReturn
return toReturn
})
}
//usage
var getData = () => axios.get('toolData.json')
.then(res => res.data)
.then(data => {
var wantedKeys=["ID","Name","Funds","BAT"]
console.log(newSubset(data,wantedKeys))
//rest of your code here
LIVE EXAMPLE
var dataArray=[{ID: 3607, Name: 'Alamo', Funds: 52933955, Revenues: 9160109, BAT: 5}, {ID: 3539, Name: 'Alvin', Funds: 6128147, Revenues: 964083, BAT: 0}, {ID: 3540, Name: 'Amarillo', Funds: 12450969, Revenues: 1716038, BAT: 0}]
function newSubset(arr,dataToSelect){
//arr is the fetched array, dataToSelect is an array of the keys(like ID,Name...) that you want from the array
return arr.map(obj=>{
var toReturn={} //object that would give each desired key for each part in arr
dataToSelect.forEach(key=>toReturn[key]=obj[key]) //placing wanted keys in toReturn
return toReturn
})
}
console.log(newSubset(dataArray,["ID","Name","Funds","BAT"]))
The data is a JSON object. It is not indexed by numbers but rather by names.
It's also recommend to use the built-in map function for this.
const tableData = toolData.map(row => ({
ID: row.ID,
Name: row.Name,
Funds: row.Funds,
BAT: row.BAT
}));
If you want the new toolData array to contain arrays instead of objects, you can instead do:
const tableData = toolData.map(row => [
row.ID,
row.Name,
row.Funds,
row.BAT
]);

How to add key value pair to the json?

I am fetching some json, but i want to add a key value pair to each object inside the array.
What i want is to add a key value pair to each object inside students array
You can do something like this:
var students = [ { city: 'California', company: 'ABC'}, { city: 'LA', company: 'PQR'}, { city: 'Mumbai', company: 'XYZ'}];
students.forEach((obj) => {
obj['email']= 'abc#xyz.com';
console.log(obj);
});
// Final Output
console.log(students);
I would suggest you simply use a for loop for each element in your array and since it's JSON simply specify a new "key = value" inside the current element.
edit : here's an example :
var entreprises = [
{id: 33, uuid: "3d103130-ae0d-11e9-8e6c-dfb1a3a5afce", nom: "test", adresse: "test", ville: "tes" },
{id: 34, uuid: "81524090-ae0d-11e9-8894-2326c7695f11", nom: "test2", adresse: "test2", ville: "test2"}];
for (let i = 0; i < entreprises.length; i++) {
entreprises[i].key = "value";
}
Start by iterating through the students array using either a foreach or standard for loop. This will give you access to each of the students, one by one. Since each of the students is an object, you will have to use either bracket or dot notation to store this new key,value pair. Here is an article that will help you determine which strategy to use for accessing keys and storing key,value pairs: Bracket notation vs Dot notation
Note: If the key you are adding already exists, you will be overriding the previous value.
For loop
for (let i = 0; i < students.length; i++) {
const student = students[i];
student[<key>] = <value>;
}
Foreach
students.forEach(student => {
student[<key>] = <value>;
});

Delete objects from array of objects

Object {Results:Array[3]}
Results:Array[3]
[0-2]
0:Object
id=1
name: "Rick"
upper:"0.67"
1:Object
id=2
name:'david'
upper:"0.46"
2:Object
id=3
name:'ashley'
upper:null
I have this array of objects as shown above. and a variable named delete_id
delete_id = 1,2
So this indicates objects with id 1 and 2. It should delete the objects in the array of objects and give the final result as follows:
Object {Results:Array[1]}
Results:Array[3]
[0]
0:Object
id=3
name:'ashley'
upper:null
Can someone let me know how to achieve this. I tried to use this below function. It only deletes the first value in variale delete_id. i.e. id with 1 is deleted. similary if we have delete_id = 2,3 then it only deletes 2. I want to delete 2 and 3 both...
function removeID(delete_id) {
tabledata = tabledata.filter(function (obj) {
return delete_id.indexOf(obj.id);
});
You can use .split() and .map() to transform your delete_id string into an array of numeric IDs. Then, you can use .filter() to do the cleanup.
var players = [
{
id: 1,
name: "Rick",
upper: "0.67"
},{
id: 2,
name: "david",
upper: "0.46"
},{
id: 3,
name: "ashley",
upper: null
}
];
var delete_id = "1,2";
var exclude = delete_id.split(',').map(Number);
players = players.filter(function(player) {
return exclude.indexOf(player.id) == -1;
});
console.log(players);
function findObj(array,value,key) {
var result = array.filter(function (obj) {
if (obj[key] === value || obj[key] == value)
return obj;
});
return result;
};
First find the object from the
array(tabledata),value=1(delete_id),key=the key in json(id)
var selectedObj=findObj(tabledata,delete_id,'id');
get index of that object in the array
var index=tabledata.indexOf(selectedObj[0]);
delete its index
tabledata.splice(index,1);
The code runs if you change the removeID code to see if the index is equal to -1
function removeID(delete_id) {
tabledata = tabledata.filter(function(obj) {
return delete_id.indexOf(obj.id)===-1; //added === -1 here
});
}
var tabledata = [{
id: 1,
name: "Rick",
upper: "0.67"
}, {
id: 2,
name: 'david',
upper: "0.46"
}, {
id: 3,
name: 'ashley',
upper: null
}];
var ids = [1,2]; //defined it as an array (not sure if you did)
removeID(ids);
console.log(tabledata);
I assume that delete_id is an integer array. In that case you can filter to exclude provided ids with code below.
It'll check if obj.id is not in delete_id, then obj will be included in a new filtered array. Also it will leave tabledata intact.
var filtered = tabledata.filter(function(obj) {
return !(obj.id in delete_id)
})

angular controller array empty even though i just defined it

the following is a function in an angular controller. "alert (coffee.brand)", or any other part of the array, prints "undefined," which obviously it isn't. The weird part is, undefined prints the correct number of times in the for loop, so it knows the array is populated, it just can't seem to read the data. thoughts? Thanks in advance!
$scope.activate = function(id){
$scope.coffees =
[
{'id': 1,
'brand': 'Folgers',
'name': 'Regular',
'country': 'America',
'reviews': [
{'rating': 3,
'comment': "gross",
'reviewer': "James"
}
]
},
{'id': 2,
'brand': 'Starbucks',
'name': 'Mocha',
'country': 'America',
'reviews': [
{'rating': 7,
'comment': 'insane!',
'reviewer': 'Bob'
},
{'rating': 5,
'comment': 'solid...',
'reviewer': 'Joe'
}
]
}
];
for (coffee in $scope.coffees){
alert (coffee.brand);
if (coffee.id == id){
$scope.currCoffee = coffee;
alert("here")
alert ($scope.currCoffee.id);
}
}
};
You are using the for in loop incorrectly. It does not iterate over elements in an array, but property names of an object. In your case, as you are using an implicitly numerically indexed array, it would be better to use a normal for loop, like so:
for (var i = 0; i < $scope.coffees.length; i++) {
var coffee = $scope.coffees[i];
alert (coffee.brand);
if (coffee.id == id){
$scope.currCoffee = coffee;
alert("here")
alert ($scope.currCoffee.id);
}
}
See the documentation over at MDN for more information about the for in loop.
You should update the for loop to
for (var i = 0; i < $scope.coffees.length; i++) {
and retrieve values like
alert($scope.coffees[i].brand);
For reference - http://plnkr.co/edit/bmuJmJO94mEzGuB3uF0K?p=preview
coffee is key not the object itself, so go like $scope.coffees[coffee].
For more information
for...in loop
It iterates enumerable own and enumerable inherited properties.

Merging many arrays into one array (JavaScript)

I'm trying to take an array of many arrays that contain many objects and manipulate it into an array of objects.
So, let's say I have an array that looks like this:
[
[
{Name: 'Josh', email: 'josh#gmail.com', Points: 33},
{Name: 'Doug', email: 'doug#gmail.com', Points: 12}
],
[
{Name: 'Josh', email: 'josh#gmail.com', Points: 11},
{Name: 'Doug', email: 'doug#gmail.com', Points: 18}
],
[
{Name: 'Josh', email: 'josh#gmail.com', Points: 2},
{Name: 'Doug', email: 'doug#gmail.com', Points: 27}
]
]​
The Desired outcome would be an array of objects that has a 'Points' property to hold an array of the points. So it would look like this:
[
{Name: 'Josh', email: 'josh#gmail.com', Points: [33, 11, 2]},
{Name: 'Doug', email: 'doug#gmail.com', Points: [12, 18, 27]}
]
This problem seems simple, but I can't seem to figure out the best way of doing this. If you want this data in a fiddle, I made this for you to play with: http://jsfiddle.net/Qhxzz/1/
Here's one way using .reduce() and .forEach(). (You'll need patches if you're supporting older browsers.)
var consolidated = data.reduce(function(holder, arr) {
arr.forEach(function(obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
});
return holder;
}, {emails:{},result:[]}).result;
And actually, we could flatten out the original Array using concat.apply(), and be left with one monolithic Array to iterate.
flat = [].concat.apply([], data);
This turns your data into this structure:
[{Name:"Josh", email:"josh#gmail.com", Points:33},
{Name:"Doug", email:"doug#gmail.com", Points:12},
{Name:"Josh", email:"josh#gmail.com", Points:11},
{Name:"Doug", email:"doug#gmail.com", Points:18},
{Name:"Josh", email:"josh#gmail.com", Points:2},
{Name:"Doug", email:"doug#gmail.com", Points:27}]
And makes the consolidation a bit simpler by eliminating the need for the inner .forEach().
var consolidated = flat.reduce(function(holder, obj) {
if (obj.email in holder.emails)
holder.emails[obj.email].Points.push(obj.Points);
else {
holder.emails[obj.email] = obj;
holder.result.push(obj);
obj.Points = [obj.Points];
}
return holder;
}, {emails:{}, result:[]}).result;
Note that this depends on the input structure being static (no recursion here). Assuming you're not using any libraries:
var result = [];
for (var i = 0; i < initial.length; i++) {
var innerArray = initial[i];
for (var j = 0; j < innerArray.length; j++) {
var item = innerArray[j];
var found = false;
// search result for an object with a matching email prop
for (var k = 0; k < result.length; k++) {
if (result[k].email === item.email) {
found = true;
// add this Point to the Points array
result[k].Points.push(item.Points);
}
}
if (!found) {
// convert Points to an array of Points
item.Points = [item.Points];
result.push(item);
}
}
}
http://jsfiddle.net/Qhxzz/2/

Categories