There are two types of arrays which I have to build dynamically.
data['fields']['title']
and
data['fields']['description']['html']
it returns the content of this structure:
{
"fields": {
"title": "Headline",
"description": {
"html": "<p>description text</p>"
}
},
"meta": {
"id": "995915463198380032"
}
}
The problem is "dynamically".
I call a function and give the path through it like "description>html".
I split the string into "description" and "html".
But how do I build now the array: data['fields']['description']['html']
Sometimes there is a level more or less like "title".
If I want to call title, the array is like data['fields']['title']
So the content and the number of parts in the array are dynamic.
I tried by myself this:
function comfort_x(item_fields) {
var splitter = item_fields.split(">");
var content = new Array();
for (var i = 1; i < splitter.length; ++i) {
content['splitter['+i+']'] = splitter[i];
}
data['fields'][splitter[0]][splitter[1]];
}
Thank you for your help.
You can create a function that will look up to the level you are passing. You can just split your path by > and reduce that array with the source input.
(data, path) => path.split(">").reduce((r, e) => r[e], data);
Here is a example.
var obj = {
"fields": {
"title": "Headline",
"description": {
"html": "<p>description text</p>"
}
},
"meta": {
"id": "995915463198380032"
}
}
var lookUp = (o, path) => path.split(">").reduce((r, e) => r[e], o);
console.log('fields: ', lookUp(obj, 'fields'))
console.log('fields>title: ', lookUp(obj, 'fields>title'))
console.log('fields>description>html: ', lookUp(obj, 'fields>description>html'))
It works with this addinitional work-around:
switch (splitter.length) {
case 0:
item.innerHTML = data['fields'];
break;
case 1:
item.innerHTML = data['fields'][splitter[0]];
break;
case 2:
item.innerHTML = data['fields'][splitter[0]][splitter[1]];
break;
case 3:
item.innerHTML = data['fields'][splitter[0]][splitter[1]][splitter[2]];
}
maybe you have a smarter solution.
/*
Be careful! The function won’t return a new object,
but take a reference to the input object aka. alter
it and don’t deep-clone it.
*/
const myObject = {};
function setValueByKeypath(object, path, value, separator = ">") {
path = path.split(separator);
let currentPart = object;
for (let i = 0, len = path.length; i < len; i++) {
const key = path[i];
const keyValue = (i === len - 1) ? value : {};
if (typeof currentPart[key] === "undefined") {
currentPart[key] = keyValue;
}
currentPart = currentPart[key];
}
}
setValueByKeypath(myObject, "fields>description>html", "<p>description text</p>");
console.log(myObject);
setValueByKeypath(myObject, "fields>title", "Headline");
console.log(myObject);
setValueByKeypath(myObject, "meta>id", "995915463198380032");
console.log(myObject);
I'm trying to perform MapReduce on this kind of data set:
{
"_id": "599861ce7ce78cd973746906",
"name": "Macias Rosario",
"col": [
{
"date": "15/03/2016",
"name": "MAGNEATO",
"amount": 313.86
},
{
"date": "08/08/2016",
"name": "FORTEAN",
"amount": 151.06
},
{
"date": "05/11/2014",
"name": "ECRATIC",
"amount": 291.68
}
]
}
Goal is to sum up all amount for name Macias Rosario. Currently I did with my code to group all by subelements this.col.name on this way:
mapper = Code("""
function() {
for (var index = 0; index < this.col.length; ++index) {
var col = this.col[index];
emit(col.name, col.amount );
}
}
""")
reducer = Code("""
function(key, values) {
var total = 0;
for( var i = 0; i < values.length; ++i){
total += values[i];
}
return value.price;
}
""")
result = collection.map_reduce(mapper, reducer, "myresult")
Has anyone have some idea how to reference, or group by this.name and not this.col.name because I don't know anymore and I'm driving nuts?
PS don't suggest me to use aggregate, did that way, want to try on this way also :)
Kind regards,
I hope the following code helps (works in pymongo as well)
This is my map function:
var mapFunction = function() {
for (var idx = 0; idx < this.col.length; idx++) {
var key = this.name;
var value = { amount : this.col[idx].amount };
emit(key, value);
}
};
And the following is my reduce function:
var reduceFunction = function(key, amountVl) {
reduceVal = { amount : 0 };
for (var idx = 0; idx < amountVl.length; idx++) {
reduceVal.amount += amountVl[idx].amount;
}
return reduceVal;
}
With your sample data it produces:
{ "_id" : "Macias Rosario", "value" : { "amount" : 756.6 } }
I am having hard time to access the particular json data. Here`s my json file
{
"id": "72",
"title": "Item Category Product Level Average Price Comparison",
"xLabel": null,
"yLabel": "Average Price",
"zLabel": null,
"data": [{
"avgPrice": "87",
"numProducts": "85"
}, {
"avgPrice": "60",
"numProducts": "49"
}, {
"avgPrice": "59",
"numProducts": "65"
}
I want to take the value of avgPrice and numProducts of the unique values first corresponding to the merchant name. For example In the json data, First and last merchantName is same(i.e "merchantName" : "A") . So I want to take the value of Merchant A first, and Merchant B(if it is repeated I want to complete that first and then go for the another Merchant.
var mn = [];
$.each(returnedData.data, function (index, value) {
if($.inArray(value.merchantName, mn) == -1) {
mn.push(value.merchantName);
}
});
//all the merchants name stored in mn[]
function get_items_by_merchant(merchant_name) {
var items = new Array();
$.each(returnedData.data, function (index, item) {
if(returnedData.merchantName == merchant_name)
items.push(item);
});
return items;
}
var CB_items = [];
for(var i = 0; i < mn.length; i++) {
CB_items[i] = get_items_by_merchant(mn[i]);
$.each(CB_items, function (index, item) {
var avgpricve = parseFloat(response.data[i].avgPrice);
var numproducts = parseFloat(response.data[i].numProducts);
datajson = {
x: avgpricve,
y: numproducts
}
result_data.push(datajson)
});
}
response is the data in json file, I am getting it using $.getJSON . In the above code I want to
access merchant name line response.data[i].mn[i].avgPrice.. Since that I am unable to.. Is there any way that I can do?
In the function get_items_by_merchant change this
$.each(returnedData.data, function(index, item) {
if (returnedData.merchantName == merchant_name) // There is not merchantName in returnedData.
items.push(item);
});
to
$.each(returnedData.data, function(index, item) {
if (item.merchantName == merchant_name)
items.push(item);
});
Final Code with changes:-
Demo
var result_data = [];
var mn = [];
$.each(returnedData.data, function (index, value) {
if ($.inArray(value.merchantName, mn) == -1) {
mn.push(value.merchantName);
}
});
//all the merchants name stored in mn[]
function get_items_by_merchant(merchant_name) {
var items = new Array();
$.each(returnedData.data, function (index, item) {
if (item.merchantName == merchant_name) items.push(item);
});
return items;
}
var CB_items = [];
for (var i = 0; i < mn.length; i++) {
CB_items[i] = get_items_by_merchant(mn[i]);
$.each(CB_items[i], function (index, item) {
var avgpricve = parseFloat(item.avgPrice);
var numproducts = parseFloat(item.numProducts);
datajson = {
x: avgpricve,
y: numproducts
}
result_data.push(datajson)
});
console.log(result_data)
Trying to split a javascript object in to a hash array.. I have to split the contents inside the array based on the occurrence of symbol"|"
my input array looks like
{
"testFieldNames": ["testNumber", "testName", "testDate1", "testDate2"]
},
"data": [
"4|Sam|2012-02-10T00:00Z",
"0|Wallace|1970-01-01T00:00Z|2012-02-10T00:00Z"
]
};
and the expected output is [{"testNumber" : "4", "testName" : "Sam", "testDate1" : "2012-02-10T00:00Z", "testDate2" : "0"},{"testNumber" : "0", "testName" : "Wallace", "testDate1" : "1970-01-01T00:00Z", "testDate2" : "2012-02-10T00:00Z"}]
This is what I've tried.. but it is not complete.
http://jsfiddle.net/Dwfg6/1/
var header = responseData.header.testFieldNames,
length = header.length,
result;
result = responseData.data.map(function(el) {
var ret = {}, data = el.split('|'), i;
for (i=0; i < length; i++) {
ret[header[i]] = data[i];
}
return ret;
});
console.log(result);
The demo. (Note: you may use jQuery.map methods instead for old browsers.)
You were close...
http://jsfiddle.net/Dwfg6/4/
var responseData = {
"header": {
"testFieldNames": ["testNumber", "testName", "testDate1", "testDate2"]
},
"data": [
"4|Sam|2012-02-10T00:00Z|2012-02-10T00:00Z",
"0|Wallace|1970-01-01T00:00Z|2012-02-10T00:00Z"
]
};
function buildData(fields, data) {
var output = [];
if (fields && fields.length && data && data.length) {
for (var i = 0; i < data.length; i++) {
var row = data[i].split("|");
output[i] = {};
while (row.length) {
output[i][fields[4 - row.length]] = row.shift();
}
}
}
return output;
}
console.log(buildData(responseData.header.testFieldNames, responseData.data));
fiddle : http://jsfiddle.net/FjJse/1/
My answer:
fiddle
function mapData (data) {
'use strict';
var result=[];
var i, j;
var values = [];
var resultObj;
for(i=0; i < data.testFieldValues.length; i += 1) {
values = data.testFieldValues[i].split("|");
resultObj = {};
for(j = 0; j < data.testFieldNames.length; j += 1) {
resultObj[data.testFieldNames[j]] = values[j];
}
result.push(resultObj);
}
return result;
}
//$(document).ready(function() {
// 'use strict';
var data = {testFieldNames: ["testNumber", "testName", "testDate1", "testDate2"],
testFieldValues: [
"4|Sam|2012-02-10T00:00Z|2012-02-10T00:00Z",
"0|Wallace|1970-01-01T00:00Z|2012-02-10T00:00Z"
]
};
console.log(mapData(data));
//});
/*Expected Output [{"testNumber" : "4", "testName" : "Sam", "testDate1" : "2012-02-10T00:00Z", "testDate2" : "2012-02-10T00:00Z"},{"testNumber" : "0", "testName" : "Wallace", "testDate1" : "1970-01-01T00:00Z", "testDate2" : "2012-02-10T00:00Z"}]*/
Hit F12 in Chrome to see console, or open FireBug in FireFox or LadyBug in Opera, etc.
How can i update the following JSON object dynamically using javascript or Jquery?
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}]
I would like to dynamically update the Username to 'Thomas' where the 'Id' is '3'.
How can I achieve this?
A plain JavaScript solution, assuming jsonObj already contains JSON:
Loop over it looking for the matching Id, set the corresponding Username, and break from the loop after the matched item has been modified:
for (var i = 0; i < jsonObj.length; i++) {
if (jsonObj[i].Id === 3) {
jsonObj[i].Username = "Thomas";
break;
}
}
Here it is on jsFiddle.
Here's the same thing wrapped in a function:
function setUsername(id, newUsername) {
for (var i = 0; i < jsonObj.length; i++) {
if (jsonObj[i].Id === id) {
jsonObj[i].Username = newUsername;
return;
}
}
}
// Call as
setUsername(3, "Thomas");
simply iterate over the list then check the properties of each object.
for (var i = 0; i < jsonObj.length; ++i) {
if (jsonObj[i]['Id'] === '3') {
jsonObj[i]['Username'] = 'Thomas';
}
}
$(document).ready(function(){
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}];
$.each(jsonObj,function(i,v){
if (v.Id == 3) {
v.Username = "Thomas";
return false;
}
});
alert("New Username: " + jsonObj[2].Username);
});
use:
var parsedobj = jQuery.parseJSON( jsonObj);
This will only be useful if you don't need the format to stay in string.
otherwise you'd have to convert this back to JSON using the JSON library.
var i = jsonObj.length;
while ( i --> 0 ) {
if ( jsonObj[i].Id === 3 ) {
jsonObj[ i ].Username = 'Thomas';
break;
}
}
Or, if the array is always ordered by the IDs:
jsonObj[ 2 ].Username = 'Thomas';
JSON is the JavaScript Object Notation. There is no such thing as a JSON object. JSON is just a way of representing a JavaScript object in text.
So what you're after is a way of updating a in in-memory JavaScript object. qiao's answer shows how to do that simply enough.
I took Michael Berkowski's answer a step (or two) farther and created a more flexible function allowing any lookup field and any target field. For fun I threw splat (*) capability in there incase someone might want to do a replace all. jQuery is NOT needed. checkAllRows allows the option to break from the search on found for performance or the previously mentioned replace all.
function setVal(update) {
/* Included to show an option if you care to use jQuery
var defaults = { jsonRS: null, lookupField: null, lookupKey: null,
targetField: null, targetData: null, checkAllRows: false };
//update = $.extend({}, defaults, update); */
for (var i = 0; i < update.jsonRS.length; i++) {
if (update.jsonRS[i][update.lookupField] === update.lookupKey || update.lookupKey === '*') {
update.jsonRS[i][update.targetField] = update.targetData;
if (!update.checkAllRows) { return; }
}
}
}
var jsonObj = [{'Id':'1','Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Username':'Albert','FatherName':'Einstein'}]
With your data you would use like:
var update = {
jsonRS: jsonObj,
lookupField: "Id",
lookupKey: 2,
targetField: "Username",
targetData: "Thomas",
checkAllRows: false
};
setVal(update);
And Bob's your Uncle. :) [Works great]
For example I am using this technique in Basket functionality.
Let us add new Item to Basket.
var productArray=[];
$(document).on('click','[cartBtn]',function(e){
e.preventDefault();
$(this).html('<i class="fa fa-check"></i>Added to cart');
console.log('Item added ');
var productJSON={"id":$(this).attr('pr_id'), "nameEn":$(this).attr('pr_name_en'), "price":$(this).attr('pr_price'), "image":$(this).attr('pr_image'), "quantity":1, "discount":0, "total":$(this).attr('pr_price')};
if(localStorage.getObj('product')!==null){
productArray=localStorage.getObj('product');
productArray.push(productJSON);
localStorage.setObj('product', productArray);
}
else{
productArray.push(productJSON);
localStorage.setObj('product', productArray);
}
itemCountInCart(productArray.length);
});
After adding some item to basket - generates json array like this
[
{
"id": "95",
"nameEn": "New Braslet",
"price": "8776",
"image": "1462012394815.jpeg",
"quantity": 1,
"discount": 0,
"total": "8776"
},
{
"id": "96",
"nameEn": "new braslet",
"price": "76",
"image": "1462012431497.jpeg",
"quantity": 1,
"discount": 0,
"total": "76"
},
{
"id": "97",
"nameEn": "khjk",
"price": "87",
"image": "1462012483421.jpeg",
"quantity": 1,
"discount": 0,
"total": "87"
}
]
For Removing some item from Basket.
$(document).on('click','[itemRemoveBtn]',function(){
var arrayFromLocal=localStorage.getObj('product');
findAndRemove(arrayFromLocal,"id",$(this).attr('basketproductid'));
localStorage.setObj('product', arrayFromLocal);
loadBasketFromLocalStorageAndRender();
});
//This function will remove element by specified property. In my case this is ID.
function findAndRemove(array, property, value) {
array.forEach(function(result, index) {
if(result[property] === value) {
//Remove from array
console.log('Removed from index is '+index+' result is '+JSON.stringify(result));
array.splice(index, 1);
}
});
}
And Finally the real answer of the question "Updating a JSON object using JS". In my example updating product quantity and total price on changing the "number" element value.
$(document).on('keyup mouseup','input[type=number]',function(){
var arrayFromLocal=localStorage.getObj('product');
setQuantityAndTotalPrice(arrayFromLocal,$(this).attr('updateItemid'),$(this).val());
localStorage.setObj('product', arrayFromLocal);
loadBasketFromLocalStorageAndRender();
});
function setQuantityAndTotalPrice(array,id,quantity) {
array.forEach(function(result, index) {
if(result.id === id) {
result.quantity=quantity;
result.total=(quantity*result.price);
}
});
}
I think this the more efficent way than for looping.
1-First find index of item.
2-Second edit exact element. (if not exist add)
Example :
let index= jsonObj.findIndex(x => x["Id"] === 3);
if (index == -1) {
// add
jsonObj.push({ id:3, .... });
} else {
// update
jsonObj[index]["Username"]="xoxo_gossip_girl"
}
var jsonObj = [{'Id':'1','Quantity':'2','Done':'0','state':'todo',
'product_id':[315,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Ray','FatherName':'Thompson'},
{'Id':'2','Quantity':'2','Done':'0','state':'todo',
'product_id':[314,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Steve','FatherName':'Johnson'},
{'Id':'3','Quantity':'2','Done':'0','state':'todo',
'product_id':[316,"[LBI-W-SL-3-AG-TA004-C650-36] LAURA BONELLI-WOMEN'S-SANDAL"],
'Username':'Albert','FatherName':'Einstein'}];
for (var i = 0; i < jsonObj.length; ++i) {
if (jsonObj[i]['product_id'][0] === 314) {
this.onemorecartonsamenumber();
jsonObj[i]['Done'] = ""+this.quantity_done+"";
if(jsonObj[i]['Quantity'] === jsonObj[i]['Done']){
console.log('both are equal');
jsonObj[i]['state'] = 'packed';
}else{
console.log('not equal');
jsonObj[i]['state'] = 'todo';
}
console.log('quantiy',jsonObj[i]['Quantity']);
console.log('done',jsonObj[i]['Done']);
}
}
console.log('final',jsonObj);
}
quantity_done: any = 0;
onemorecartonsamenumber() {
this.quantity_done += 1;
console.log(this.quantity_done + 1);
}
//update & push json value into json object
var sales1 = [];
if (jsonObj && Object.keys(jsonObj ).length != 0) {
jsonObj .map((value) => {
const check = sales1.filter(x => x.order_date === String(value.order_date).substring(0, 10))
if (check.length) {
sales1.filter(x => x.sale_price = Number(x.sale_price) + Number(value.sale_price))
} else {
let data = { "sale_price": Number(value.sale_price), "order_date": String(value.order_date).substring(0, 10) }
sales1.push(data)
}
})
}
You can easily update the username dynamically to 'Thomas' where the 'Id' is '3' using the following.
jsonObj.find(i=>i.Id===3).Username='Thomas'