Add new attribute to an existing JSON inside FOR loop - javascript

I am trying to populate bootstrap-carousel with some more detailed JSON file from database.I am adding JSON details for the sake of detailed understanding. Earlier My JSON file was :
old.json
[
{"screen": [{
"img" : "../static/images/product/34.jpg",
"price": "Rs 100",
"href": "#mobile/1234"
},{
"img": "../static/images/product/34.jpg",
"price": "Rs 101",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 102",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 103",
"href":"#mobile/1234"
}
]},
{"screen": [{
"img" : "../static/images/product/34.jpg",
"price": "Rs 100",
"href": "#mobile/1234"
},{
"img": "../static/images/product/34.jpg",
"price": "Rs 101",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 102",
"href":"#mobile/1234"
},{
"img":"../static/images/product/34.jpg",
"price": "Rs 103",
"href":"#mobile/1234"
}
]}
]
Now, I am trying to populate it with some more detailed JSON file.
new.JSON
[
{
"sku": "d58a2ece-4387-41d0-bacb-c4b7935f8405",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "obviate buffoonery exterminating knave uncertainly engulf radiantly dogmatist squadron overcame refinance mopes pastier microphone awaiting begin extinguish plenty prod antecedent holdout schoolmarms Rush Kurosawa clinic Broadways Brie sunnier drove ermine husk gendarme vizier Mithridates feast goggled phase purchasing savviest prologs emails resets admire kilotons maladjustment burns viscounts puked receive Tibetans classifications kneed filtration thorns supply bigness astigmatic butterier differential sensational modernistic Djakarta splint earplug boomed horticulture perishables chanticleers syndicated scantiest cantankerousness splashier variate gneiss permutations typeset protozoa wrangled lawbreakers rumbling describe acerbity revenged golfs stalwart stockading caricatures pannier unpleasant sitter rescinds hazing Burgess coastlines thieved encouragingly forefinger Walpole achieving began spec diabetes Lichtenstein hickory squanders borne compute required bringing remunerative Oreo Pekingeses visualized sociopaths radicals flowerier Pakistan terse fillets barking causes Casey manpower ram glamourize deserves Steuben privatized waterproofs ridding poisons discredits overlong coquettes lichees proclivity floating thousandth Linwood promenading mushroomed stain strode obtusest transiency buckets vanguards straying castigate fathom Sappho restricting rehabilitation restiveness pattered bluest box lacquer noticeably Douro overdone biennially diodes baroque hesitant cleaving corroborates reminiscing disks abundant seven used peremptory employment matchbook fraternizing marigold Diaz vaporizers uncork Royal quick absurder misanthropic nabob blindfolds contemplatives Poincaré Galapagos Willamette punctilious Concord Othello carpal leanness Viacom snorkelers arcs piggybacking pulverized",
"selectedQty": "1",
"title": "dibble",
"brand": "Brand7",
"images": [
{
"image0": "/media/products/9f9734f60620cb52246e9e995b75a9bb.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "upraised saline frowzy rails clampdown Geritol answer devoutest pressure silky",
"measureUnit": "ltr",
"discountPercent": 3,
"mrp": 8472,
"qty": 6,
"size": 99
},
{
"discountAttributes": "servers ambitiousness billeted brutalized moonstone clerestory Pole hamlet Shelton testaments",
"measureUnit": "ltr",
"discountPercent": 20,
"mrp": 2477,
"qty": 4,
"size": 19
},
{
"discountAttributes": "reeducated schmaltz gnashes marketplaces spill gazetteer bethinks preheats duel parley",
"measureUnit": "gms",
"discountPercent": 13,
"mrp": 6162,
"qty": 9,
"size": 86
}
],
"id": 1
},
{
"sku": "b8ea355d-7acc-455b-a55c-027b0e5c73cd",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "Krasnodar karats northeasters libertarian aromatherapy badly partings sexpot rectangular Pyrenees yeshivahs gybe hollowness attune reuse Alphard Chilean johns Clydesdale acronym marmots itched proposer lushes hush combinations Latino weeps starches Hinayana firmware gamy society gaggle mast ginseng sordidness spiritualist sacking southern niceties grunting oblation arbor measures hobo measured iPad respites rutting sickened Baylor torturers malingers deferring expurgations tighter tenderfoot upload hosteling Apollonian upscale wraps Suzhou bookworm clarioning Ismail filthiest arborvitae descender accountant rendezvousing Didrikson mesquite sedating warlocks whips filigrees skylarking wallet refill inveighs thatch toffees recognizable Nazca foresails clangor eliminate crapped gourds impinges relinquishing duh drizzliest false uncommitted exhibited inhalation fomented crestfallen Bacall Darwinism Laurel gays peter undiluted showoff groceries sleeting immaturity Barclay whimpered Madeleine typhoons afforesting Theodoric beaching Decker merriness cultures luggage subscriptions Thomas map stun lengths Jackie offshoot Condorcet squirting upholstering amber statures unmanning snuck expatriates Gethsemane mongeese rocket reappearances Mantle marinading grotto twinkled stonewalling intermarried yoga vassal magnums parking convening Senecas sculled crimps undisciplined Montoya matchstick Sarah scissors intellects replay Rover seduce forage land Platonic wafer medicinal wooding Cumberland ravishing plummeting bantam choking rhizome Wei skyrocketed tempting concretely Siberia boxed heliotropes crummy alliteration reappears Budweiser lecher blunts supplications perspiring corrective military scurvy so monitoring tossed thymi saprophyte riverbed",
"selectedQty": "1",
"title": "nark",
"brand": "Brand2",
"images": [
{
"image0": "/media/products/2f08f1c38a7b67956e4f9295b6898f36.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "towns Emily chafing boozers secrete confidentially primitively hospices disarrange misplaces",
"measureUnit": "gms",
"discountPercent": 8,
"mrp": 9942,
"qty": 8,
"size": 67
},
{
"discountAttributes": "amateurish tribune luxuriates staged severity Mia spices Muenster coercion obscure",
"measureUnit": "ml",
"discountPercent": 18,
"mrp": 3104,
"qty": 8,
"size": 43
},
{
"discountAttributes": "hanger hassling misanthropists scary dimly economists Moslem castaway Elam initiative",
"measureUnit": "gms",
"discountPercent": 17,
"mrp": 6260,
"qty": 6,
"size": 72
}
],
"id": 2
},
{
"sku": "7e46f4b1-a083-4eab-8d41-ac594202bd8f",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "avails leg whisking lamaseries rebuilding syllabifying clammiest pretense redcap bellying healthy spaghetti Velveeta shares refunding yellowed danced Peking Darrin pigging illegibly foreign utterly Shakespearean trammelling reports Moran tab okra yipped motorcyclists sweetheart sickbed Serb disgorging Sawyer the incinerator selects each reheats declaimed equestriennes Rolvaag membrane tinselled propagation sighs engraved spookier splurged neuters impersonator Gloucester condemnatory adumbrate citadels Iaccoca mishandled clamming scurries militancy interviewing seized mestizoes lithe Marrakesh isolationism antimatter gossip humanitarians combated tease battering idlers sunset Quaternary striving pattern Brandon heart upended barbiturate overtakes pendant tripe doomsday pejoratives paltriness share tadpoles warming intern fluorides Arawakan honcho sleepiness incorporates typesetters alphabetizes violinists Flanders publicist informer deathbed getaways Iyar Decca schmoozing Tricia ultrasound debugging trepidation suspenseful scrapping rubies exorcized riffling vasectomy tolled bootblack Lott balking PhD hitched utter reprehends snorkel dodges deck dynamical planting conspicuously mottoes totality bedecking bachelor wooed mummification risks Chase weatherproof pear backboard Lieberman fisherman propositional swig ruminants Deena pastiche snob overshadowing spinet apostasy immigrated weighing Christie upraised accruals amphitheatre southwester bulldogs Caracas Trajan primly snowsuit bottomed Woolworth predate biking drill japans potholders uncommon swagging oversteps appositive razing helixes ninetieths prohibitory careered Costello musketeers orator pothooks dumfound express hopelessly franchisers blames semimonthlies transformers histogram radiator canes photoelectric pelves bruised",
"selectedQty": "1",
"title": "Harare",
"brand": "Brand8",
"images": [
{
"image0": "/media/products/2f08f1c38a7b67956e4f9295b6898f36_btZCYFi.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "deters pyrite excitement Australian wadi protagonists bumpiest Caxton bundling monotony",
"measureUnit": "ltr",
"discountPercent": 5,
"mrp": 9355,
"qty": 1,
"size": 80
},
{
"discountAttributes": "puppies smudge moderator constellations invasion Asgard goggle compendiums atrophy tents",
"measureUnit": "Kg",
"discountPercent": 7,
"mrp": 4183,
"qty": 2,
"size": 19
},
{
"discountAttributes": "jailer allotting kindness veers Moss invalidation Brahmanism xenophobia warmhearted looping",
"measureUnit": "ml",
"discountPercent": 16,
"mrp": 1956,
"qty": 1,
"size": 33
}
],
"id": 3
},
{
"sku": "d1cd71a8-9dc5-4724-b269-473ede28a1d7",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "foolish interpolates trumpet monographs ferried inboards Forster tike grammatically sunroof vaporizing Sweden demure retouching completely robbing readies unloose guiltless tatty unobservant cuffs fortieth wither rigorously paradoxically snowmobiling charts clenching planning dealing lesions bicameral pertly chaffinches grumpiness private purled insanely attainment proposal Fatima execrates pshaws chars actuators turboprop soughed kicking majors conquistadores Cynthia septuagenarians kneecaps titans attractions larvas invigorating trunking Shevat recluse Trina slenderness kinking falsified logistically hogged skyrocketing ordinal avoiding trademarked underfoot garter sacrificial pricey nosedive bachelors deiced heave dictatorial muffing prayed rewinding recopied limpidly Crichton conversion chitterlings signets Aiken Froissart turnoff snowshoe forded spiralled underwriters flourishes Sade splicer transfusions cesspools lifelike ruckus showering paean voguish Buck copings Russell watchdog magneto pored height zodiac motherland backings Venus obeys scooters nonintervention dinosaur unashamedly anathema hibernate consumerism portended worked mystically existentialist dissatisfies badgers unanimously triplicated Jenny sagacity Windex snoopier nonplusing shovelling Assam putty darn Sulawesi Italians gunnery codify develops rhinos upwards Louise welled experiences socks pinky mewed Camille claimants swirl squattest ware parenthetic bonitoes hydrangeas decolonizing omit skyjacks Gorky financiers province flywheel southeastward Bayeux updated yowl Tulsidas macintosh sprees pralines systolic uncommoner cilium tromping Asimov heinous cordoned combated camerawomen syndrome identified prizefights heavyweight vertically reflector integrity Hebrides sepulchral loner parrot smooths candidness",
"selectedQty": "1",
"title": "viragoes",
"brand": "Brand0",
"images": [
{
"image0": "/media/products/f791a316ced7b3b774bd61e138197224.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "chinos theosophy misdemeanor irrigates school Pullman sombrely suspect vortex baddest",
"measureUnit": "ltr",
"discountPercent": 4,
"mrp": 3102,
"qty": 7,
"size": 66
},
{
"discountAttributes": "Molotov absurd traces pounces contracts clarions thighbone Hesse parricide constrains",
"measureUnit": "m",
"discountPercent": 16,
"mrp": 2773,
"qty": 7,
"size": 18
},
{
"discountAttributes": "detainment gunnysack vied expropriation unobtrusive collectables embracing poster hexing governess",
"measureUnit": "m",
"discountPercent": 6,
"mrp": 9920,
"qty": 6,
"size": 69
}
],
"id": 9
},
{
"sku": "838660bb-7ab9-4f2a-8be7-9602a5801756",
"selectedQtyOptions": [],
"selectedSize": "",
"description": "agreeing vizier bleariest trig appliquéing copulating commissariats Balzac lunchtimes glittery quacking Leoncavallo heehawing Tampax lizards pegged nanosecond centigrade subplots tumbrils give jawed skits nickel discontinues impinged evangelized Platonist waterlines dams symposiums intercessor cognition heavier softener dromedaries bravos immobilize consciously Clemons patch klutzier Kirkpatrick caddying designs Dulles twelfths undemocratic isolationists infected ma homering soliciting minibus pluralism fraternity catalyzed Scorpio pandemonium waxwing starter infuses rebuttals spirals rerunning interrogatories Manuel whomsoever tenderized conjoint baronesses callower parenthetic plusses extend cockier Fokker dewlap Cowper Swammerdam secs hock relaxations Judas Canadian presidency lo wildness Philippe picture beekeeper lull manuals transnational yaw chloroformed perennials distinctive Nottingham antiquaries underneath parted nervously basemen observatories scrubbed encoder egalitarians winnow caddish Hawaiians brownstones robbing exhaustible antagonist benefactresses Plasticine Peace platypi Guzman stippled shuts peacemakers butterfly Bolton grout McCain Lebanon bounce oleander Balkans endearments snowfall spoonerisms furnaces inequities billowy jutting guffaw beautifully penis newtons snuffboxes j Angelita tinkles literature depicts insouciant scribblers blinker disobediently devotees primordial sixties Kalamazoo shear contest classes cripple edging exactest cheat invocation thrived drunkenness Fuller architectures sprite Lillian constricts tucking chastisements walruses guzzlers rejoinder apprenticeships pillory spendthrift omens spoonful contortions precociously intensely motorway guts cahoot sculptor paralytics reminisce meltdown trusts lady pronghorn scurried Campbell micron flawing foals nigher",
"selectedQty": "1",
"title": "smokier",
"brand": "Brand2",
"images": [
{
"image0": "/media/products/f51a649e72694d23962ee77a97872f0e.jpg"
}
],
"sizeQtyPrice": [
{
"discountAttributes": "Beerbohm earldom Stanley seconding hypertension Sayers miserly epitome retires ditching",
"measureUnit": "m",
"discountPercent": 15,
"mrp": 5065,
"qty": 6,
"size": 83
},
{
"discountAttributes": "confine Newman bagel cornflower rears generator goaded midweeks drain cigarillo",
"measureUnit": "Kg",
"discountPercent": 12,
"mrp": 2284,
"qty": 9,
"size": 13
},
{
"discountAttributes": "eerier fizzes lessened rotisserie developer Gray industrial callused convergences ampoule",
"measureUnit": "gms",
"discountPercent": 4,
"mrp": 6816,
"qty": 8,
"size": 18
}
],
"id": 14
}
]
As you can see, I need to group my new.JSON as a group of 4 under screen attribute. For that I wrote one for loop:
mainApp.controller('MultiCarouselController', function($scope, $http) {
$scope.products = [];
$scope.Math = Math;
$http.get("/get_broad_category_products/?BroadCategory=BroadCategory3")
.success(function (response) {
$scope.products = response;
var iteratation = Math.ceil($scope.products.length/4);
var carouselJson = [];
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]) // concatenating 4 JSON as a group
}
carouselJson.push(temp); // pushing group to new JSON
}
console.log(carouselJson);
}).error(function(){
console.log('Error happened ... ');
});
});
This angularJS controller is working completely fine, how can I add "screen" property and then add group of 4 JSONs to it
I though about doing something like:
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]) // concatenating 4 JSON as a group
}
var jsTemp = [] ;
carouselJson.push(jsTemp.screen.push(temp)); // Errrrr.... screen property is not there in jsTemp. Now ????
}
Small help might do the trick !!!

I am not at all a fan of angular so do not know that much about how it handles JSON.
Yet JSON is just a serialized object and thus it is easy to mix and match as long as you take a few precautions.
Consider the following two json files. JSON1 is a list of products and each product has an id that is unique to that product. The second JSON JSON2 has amendments to the first JSON that have specific names "extraImages", "newItems", "updates", "newData" that we have to add to the first.
Concatenating them will not do as they are not arrays. nor can you just concat JSON strings, it does not work.
You could write a generic Object join function but that will join the two without any contextual knowledge. How does it know where to put extra images? how does it know that each product can be identified by the ID?
To join the two object we need to have pria knowledge of the data structures and the semantic meaning of each item in both files.
Anyways the two JSON files as string.
var JSON1 = `{
"item1":{
"id":100,
"desc":"a product",
"images":[
"img1.jpg",
"img2.jpg",
]
},
"item2":{
"id":101,
"desc":"another product",
"images":"img11.jpg", // this item has only one image so it just has a string
},
"item5":{
"id":105,
"desc":"a product without images",
},
}`;
var JSON2 = `{
"extraImages":[{
"id":101,
"images":[
"imageA.png",
"imageC.png"
]
}],
"newData":[{
"id":100,
"price":100,
}
],
"update":[{
"id":100,
"desc":"Best buy product",
}
],
"newItems":[{
"item3":{
"id":102,
"desc":"Just on the docks",
"images":[
"Blury11.jpg",
]
},
}
}`
So as strings JSON is kind of useless. To hard to search and find data. So JavaScript has a built in object to handle JSON called funnily enough JSON
The JSON object has two methods JSON.stringify(Obj) and JSON.parse(String)
JSON.stringify takes a basic JS data type and converts it into a
JSON string.
JSON.parse takes a json string, from whatever source and converts
it back into a JS Object, Array...
So first step convert both JSON string to objects.
var items = JSON.parse(JSON1);
var extras = JSON.parse(JSON2);
Now we have two normal JS objects that we can manipulate and join.
Lets do the images. The extra images are an array, with each item having an ID and an array of image names.
// we know the name of the object that has extra images so check if its there
// and then itterate all the items in the array
if(extras.extraImages !== undefined){ // Does this property exist
extras.extraImages.forEach(function(item){ // itterat over each item
var arrayOfImages;
// do the images exist and if so are they as an array
if(item.images !== undefined && typeof item.images === "array"){
arrayOfImages = item.images;
}
// the data structure may vary depending on what is serving the JSON
// data so you can add code to take differing types
// Now to find the matching item in the items object
// check that there is an array of images to add and tha
// the item we have has an item id we can use to find the existing item
if(arrayOfImages !== undefined && item.id !== undefined){
// continue on further down
So we have found an extra images item that has an ID and array of image names. We need to find the product if it exists that has that ID. As we will do that many times lets write a function to do that.
// pass the items object that may contain the item with the ID we are looking for
function getItemById(items,id){
for(var itemName in items){ // iterate each named item. itemName is
// just a variable it could be any var name.
// It contains a string holding each enumerable
// properties name in turn
Now check that the named property has a id you may be tempted to check if the id has the id we are looking for.
if(item[itemName].id === id){
This will throw an error if the item does not have an id and there are many reasons an enumerable property may appear that is not correctly structured. So check id exists then check its value. Unlike C/C++/C# the order of comparisons is always left to right. At the first false the if( will drop out of the () and not do any further comparison.
It is thus safe in javascript to test for the second condition as long as you test first that it will not throw ReferenceError: id is not defined
if(items[itemName].id !== undefined && items[itemName].id == id){
will never throw an error while
if(items[itemName].id == id && items[itemName].id !== undefined ){
can if id does not exist.
Anyways I diverge.
if(items[itemName].id == id && items[itemName].id !== undefined ){
// found the item with matching id
return items[itemName]; // so return it
}
}
return undefined; // nothing found that matches so return undefined
} //end of function
So back to adding extra images. We have just tested and found a extraimage item with an id and some extra image names.
// use the function to get the item
var existingItem = getItemById(items,item.id);
// check that we found one
if(existingItem !== undefined){
// check to see if it has a images
if(existingItem.images === undefined){
// no image so creat images and add an empty array
existingItem.images = []
}else // if it does is it an array
if(typeof existingItem.images !== "array"){
// not an array we will assume what is there
// is an image description of some type
// so convert the existing images object into
// an array and add the existing item into it
existingItem.images = [existingItem.images];
}
// now we are sure the images array is correct so lets
// add the new images to i
existingItem.images existingItem.images.concat( arrayOfImages);
}
}
}); // end of forEach lop
} // endo of adding new images
So wrap it all up
// code to join extraImages to items
if(extras.extraImages !== undefined){
extras.extraImages.forEach(function(item){
var arrayOfImages;
if(item.images !== undefined && typeof item.images === "array"){
arrayOfImages = item.images;
}
if(arrayOfImages !== undefined && item.id !== undefined){
var existingItem = getItemById(items,item.id);
if(existingItem !== undefined){
if(existingItem.images === undefined){
existingItem.images = []
}else
if(typeof existingItem.images !== "array"){
existingItem.images = [existingItem.images];
}
existingItem.images existingItem.images.concat( arrayOfImages);
}
}
});
}
// was going to show all the other joins for extras.update, newItems, and newData
// too much for one answer.
I see this is becoming a long answer. I'll assume that you see what is being done and how that is used to join two objects together while conforming to its semantic meaning. You should be able to write a function to do the same for your data. Convert both JSON strings to object via JSON.parse iterate the object structure obeying the semantic meaning of the data, creating or appending data as needed.
The last thing, as I assume you need the joined data as JSON string, is to convert the updated object back into a json string.
JSON1 = JSON.stringify(items); // convert the updated items object to a JSON string
Now you can pass it on back to Angular's JSON abstraction layer to do what you need.
Hope this helps. And maybe there is a way in Angular but as no one has answered with what is needed and I don't want to sully my purist ways (yucky Angular), this will give you some extra JS grounding and allow you to fix your problem.

If I am reading this correctly, you want a new property to be added to each element inside the temp array. For this you can try creating a new object from your $scope.products[i].
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
var destObj = $scope.products[i];
destObj.screen = 'xx' // Assign your value here.
temp = temp.concat(destObj) // concatenating 4 JSON as a group
}
carouselJson.push(temp);
}
Hope this helps...

this linked helped me
JavaScript Array Push key value
changed my loop like:
var carouselJson = [];
for(var index = 0; index < iteratation; index++){ // kinda 2D matrix as [0,1],[0,2],[1,1],[1,2]
var temp = [];
var screen = ['screen'];
var obj = {};
for (var i = (index*4) ; i < (4*(index+1)) ; i++){
temp = temp.concat($scope.products[i]); // concatenating 4 JSON as a group
}
obj[screen]=temp;
carouselJson.push(obj); // pushing group to new JSON
}
$scope.mCarousels = carouselJson;

Related

Return Javascript child array based on parent filter

Disclaimer: I know some Java but almost nothing about Javascript and have about 2 days to fix someone else's issues, of which this is one small part.
I have a nested array. I know the shop number, but need to get an array of only the parts in that shop.
"shops": [
{
"shopID": "15231",
"city": "Anytown",
"state": "MO",
"inventory": [
{
"description": "filter",
"partnumber": "MGL57047",
"shelf": "Z",
},
{
"description": "filter",
"partnumber": "84060",
"shelf": "A",
}
},
{
"shopID": "15232",
"city": "Springfield",
"state": "IL",
"inventory": [
{
"description": "filter",
"partnumber": "MGL57048",
"shelf": "B",
},
{
"description": "filter",
"partnumber": "84061",
"shelf": "A",
}
}
Here's what I tried:
const enteredShopID = '15231' // This isn't hard-coded in my app.
// Pull the list of all consumables for the current shop
var currentShop = application.data.shops.filter(s => s.shopID == enteredShopID)
This gets me an array with the shop and all of the inventory for that shop, but I need an array of the inventory. I tried
var currentShop = application.data.shops.inventory.filter(s => s.shopID == enteredShopID)
but that didn't work. Really, I'm just fumbling here. Is there a way to make the latter statement work, and somehow refer to the shopID of the parent?
Just use map() after the filter.
var currentShop = application.data.shops
.filter(s => s.shopID == enteredShopID)[0]
// checking if the current shop is actually null because no shops matched the ID
var currentShopInventory = (currentShop || {}).inventory || []
or use find()
// Note: If you use find(), there's a chance that there is no matching object
// So you'll have to check for that before you access the "inventory" key
// Otherwise you'll get "Cannot access 'inventory' of null"
var matchingShop = application.data.shops
.find(s => s.shopID == enteredShopID)
// Doing the checking here using an "or" if the matchingShop is null
var currentShop = matchingShop || {}
var currentShopInventory = currentShop.inventory || []

How to check if JavaScript objects differ from each another

I'm trying to compare 2 arrays of objects, and am currently doing it by using Array.length() which does not seem to be the right way based on what I'm trying to achieve.
I have these two Arrays of objects:
const array1 = [
{
"book_id": 285,
"status": "Borrowed",
"attributes": [
{
"name": "To Kill a Mockingbird",
"description": "Published in 1960, this timeless classic explores human behaviour and the collective conscience of The Deep South in the early 20th century. Humour entwines the delicate strands of prejudice, hatred, hypocrisy, love and innocence to create one of the best novels ever written.",
"borrowed_by": "John"
}
]
},
{
"book_id": 284,
"status": "Borrowed",
"attributes": [
{
"book_name": "ATTRIBSAMP 1",
"description": "Although 1984 has passed us by, George Orwell’s dystopian, totalitarian world of control, fear and lies has never been more relevant. Delve into the life of Winston Smith as he struggles with his developing human nature in a world where individuality, freewill and love are forbidden.",
"borrowed_by": "Bob"
}
]
}
]
VS
const array2 = [
{
"book_id": 285,
"status": "Free",
"attributes": [
{
"name": "To Kill a Mockingbird",
"description": "Published in 1960, this timeless classic explores human behaviour and the collective conscience of The Deep South in the early 20th century. Humour entwines the delicate strands of prejudice, hatred, hypocrisy, love and innocence to create one of the best novels ever written.",
"borrowed_by": ""
}
]
},
{
"book_id": 284,
"status": "Borrowed",
"attributes": [
{
"book_name": "ATTRIBSAMP 1",
"description": "Although 1984 has passed us by, George Orwell’s dystopian, totalitarian world of control, fear and lies has never been more relevant. Delve into the life of Winston Smith as he struggles with his developing human nature in a world where individuality, freewill and love are forbidden.",
"borrowed_by": "Bob"
}
]
}
]
Basically I want to check whether there are changes between the two, i.e. borrowed_by and/or status, I understand now that array1.length will be equal to array2.length since the array length would always be equal to 2. Is there an easier or better way to check this?
Expected output, I would like to call function callFunction1():
if(compare(array1,array2){
callFunction1();
} else {
null;
}
I currently have:
if(array1.length !== array2.length){
callFunction1();
} else {
null;
}
To close the question, I went with Lodash's _.isEqual for comparison
if(!_.isEqual(array1, array2){
callFunction1();
} else {
null;
}

Creating an efficient JSON mapping for JavaScript

We have a situation that can be best described in terms of an analogy. Let us assume that we have a mapping between name and city+state+zipcode. Here the name is guaranteed to be unique. Our sample data (adapted from here) is as follows:
James Butt: New Orleans LA 70116
Josephine Darakjy: Brighton MI 48116
Art Venere: Bridgeport NJ 8014
Lenna Paprocki: Anchorage AK 99501
Donette Foller: Hamilton OH 45011
Simona Morasca: Ashland OH 44805
Mitsue Tollner: Chicago IL 60632
Leota Dilliard: San Jose CA 95111
Sage Wieser: Sioux Falls SD 57105
Kris Marrier: Baltimore MD 21224
What would be a good JSON structure in this case? We are looking for something that is more efficient, from a processing perspective, for JavaScript. We see at least two options.
Option 1
{
"James Butt": "New Orleans LA 70116",
"Josephine Darakjy": "Brighton MI 48116",
"Art Venere": "Bridgeport NJ 8014",
"Lenna Paprocki": "Anchorage AK 99501",
"Donette Foller": "Hamilton OH 45011",
"Simona Morasca": "Ashland OH 44805",
"Mitsue Tollner": "Chicago IL 60632",
"Leota Dilliard": "San Jose CA 95111",
"Sage Wieser": "Sioux Falls SD 57105",
"Kris Marrier": "Baltimore MD 21224"
}
Option 2
[
{
"name": "James Butt",
"address": "New Orleans LA 70116"
},
{
"name": "Josephine Darakjy",
"address": "Brighton MI 48116"
},
{
"name": "Art Venere",
"address": "Bridgeport NJ 8014"
},
{
"name": "Lenna Paprocki",
"address": "Anchorage AK 99501"
},
{
"name": "Donette Foller",
"address": "Hamilton OH 45011"
},
{
"name": "Simona Morasca",
"address": "Ashland OH 44805"
},
{
"name": "Mitsue Tollner",
"address": "Chicago IL 60632"
},
{
"name": "Leota Dilliard",
"address": "San Jose CA 95111"
},
{
"name": "Sage Wieser",
"address": "Sioux Falls SD 57105"
},
{
"name": "Kris Marrier",
"address": "Baltimore MD 21224"
}
]
Option 1:
This is a bad idea even if you are completely certain there are no duplicate names. Firstly, there is no real-world situation in which there are no duplicate names. Secondly, what if the name contains a special character?
Option 2:
This is the right way to format the data, except as noted in the comments there should also be a unique ID field mapped to each name.
const data = [
{
"id": 1,
"name": "James Butt",
"address": "New Orleans LA 70116"
},
...
];
user = data.filter(({id})=>id==1); //gives you this user
user = data.filter(({name})=>name=='James Butt'); //also works
The reason to add the unique ID inside the data construct is to avoid relying on the order these are inserted into the data array. Any data coming from a real world database will always have some sort of unique ID field, which may be numeric or alphanumeric. But the order in which that data is returned will not be a reliable indicator of what the true id of the user is.
Not sure what you really mean by "processing efficiency", but guessing you would like to efficiently look up people addresses by their names. The proposed solutions require iterating over entire collection, so they'll work on 500 records and won't on 1M.
Also, as other people have mentioned, name collisions are real (especially when you get that 1M records set), so assuming you need two features from your data structure:
efficient address lookups by name;
no name collisions.
This means you need a multimap where keys are people names and values are sets of addresses. Basically, your first option with arrays of addresses as field values. Alternatively, you can use a Map for more efficient additions/removals and easier access to the number of records (unique people names) stored.
Maps (and Sets) in V8 implementation are said to have O(1) time complexity vs the linear time when using arrays. So they're efficient.
Speaking of efficiency (and to prevent duplicated name-key clash)
I'd map the string-data into an Object where keys are Unique IDs (just like in a database):
{
7 : {
"id": 7,
"name": "James Butt",
"address": "New Orleans LA 70116"
},
19 : {
"id": 19,
"name": "Josephine Darakjy",
"address": "Brighton MI 48116"
}
}
Extracting a single record:
We gain the speed by immediately extracting a record given a key ID just like a lookup for a memory address - instead of always iterating the (in the worst case - the entire) array in search for a single record.
Extracting Multiple records:
You can always iterate Objects using Object.keys(), Object.values() or Object.entries() - and loop, just like you would with Array.
Since from ES2015 object keys order is predictable, you can effortlessly have the Object ordered by ID out of the box - giving that by default the records are organized by creation-date - since DB rows IDs are incremental.
Example: Get record by ID or Value
const users = {
6 : {
"id": 6,
"name": "Antonette Darakjy",
"address": "Brighton MI 48116"
},
7 : {
"id": 7,
"name": "James Butt",
"address": "New Orleans LA 70116"
},
19 : {
"id": 19,
"name": "Josephine Darakjy",
"address": "Brighton MI 48116"
},
};
// GET BY ID
console.log(users[7]); // No need to iterate tens of thousands of records
// GET BY KEY VALUE
// Return an array of filtered users
const filterBy = (prop, val) => Object.values(users).filter(user => {
return user[prop] === val;
});
console.log(filterBy("address", "Brighton MI 48116"));

AngularJS : custom iterations/data transformations and grouping... when simple ng-repeat just won't cut it

Still this problem Angular.js more complex conditional loops but I felt that the answer to the question as it was asked was right so I accepted it.
So let me elaborate more than I did in the original question.
I'm trying to get this
<h3>11.4.2013</h3>
<ul>
<li>oofrab | 4 | 11.4.2013 14:55 <button>remove</button></li>
<li>raboof | 3 | 11.4.2013 13:35 <button>remove</button></li>
</ul>
<h3>10.4.2013</h3>
<ul>
<li>barfoo | 2 | 10.4.2013 18:10 <button>remove</button></li>
<li>foobar | 1 | 10.4.2013 12:55 <button>remove</button></li>
</ul>
from this data structure
[
{
"id": 4,
"name": "oofrab",
"date": "2013-11-04 14:55:00"
},
{
"id": 3,
"name": "raboof",
"date": "2013-11-04 13:55:00"
},
{
"id": 2,
"name": "barfoo",
"date": "2013-10-04 18:10:00"
},
{
"id": 1,
"name": "foobar",
"date": "2013-10-04 12:55:00"
}
]
Basically the only extra thing over the standard ng-repeat I want to add are those headings. And I simply can't believe I'd have to go thru so many problems by adding them.
This is what I ended up with using the answer I got in the first question http://plnkr.co/edit/Zl5EcsiXXV92d3VH9Hqk?p=preview
Note that there can realistically be up to 400 entries. And I need to be able to add/remove/edit entries on the fly
What the example on plunker is doing is this:
iterating thru the original data creating a new data structure looking like this
{
"2013-10-05": [
{
"id": 4,
"name": "oofrab",
"date": "2013-10-05 14:55:00",
"_orig_index": 0
},
{
"id": 3,
"name": "raboof",
"date": "2013-10-05 13:55:00",
"_orig_index": 1
}
],
"2013-10-04": [
{
"id": 2,
"name": "barfoo",
"date": "2013-10-04 18:10:00",
"_orig_index": 2
},
{
"id": 1,
"name": "foobar",
"date": "2013-10-04 12:55:00",
"_orig_index": 3
}
]
}
allowing me to then get the result I wanted by doing this
<div ng-repeat="(date,subItems) in itemDateMap">
<h3>{{date}}</h3>
<ul>
<li ng-repeat="item in subItems">
{{item.name}} | {{item.id}} | {{item.date}}
<button type="button" ng-click="removeItem(item._orig_index)">x</button>
</li>
</ul>
</div>
Great. But it comes with a cost of shizzload of problems. Everytime a new item is added I have to rebuild the itemDateMap, everytime an item is deleted I have to rebuild the itemDateMap, everytime date is changed, I have to rebuild the itemDateMap. When I want to remove an item, I have to first get index of its original reference. And everytime itemDateMap is rebuilt, the whole thing is re-rendered. And it can't be sorted, as it's an object rather than an array.
When there's a couple of hundred of entries, it also becomes really, really slow. I read somewhere that ng-repeat is quite intelligent, watching values, moving nods in dom rather than re-rendering everything and stuff, but it surely doesn't work this way when I rebuild the whole structure.
This can't be right, all this hassle to do a very, very simple thing..
What should I do?
This is my suggestion - just work with one structure, and only expose one structure to the scope (the map). And create a function to add an array of items to the map, and a function that transforms the map into an array (I assume you need this array for server communication or something).
var toKey=function(item){
return moment(item.date).format("YYYY-MM-DD");
}
$scope.itemDateMap = {};
$scope.addItemToDateMap=function(item){
var key = toKey(item);
if(!$scope.itemDateMap[key]){
$scope.itemDateMap[key] = [];
}
$scope.itemDateMap[key].push(item);
}
$scope.removeItemFromDateMap=function(item){
var key = toKey(item), subitems = $scope.itemDateMap[key];
var index = subitems.indexOf(item);
subitems.splice(index,1);
if(subitems.length === 0){
delete $scope.itemDateMap[key];
}
}
var addArrayToMap = function(items){
for(var i=0; i<items.length; i++){
var item = items[i];
$scope.addItemToDateMap(item);
}
};
$scope.mapToArray = function(){
var items = [];
for(var key in $scope.itemDateMap){
var subitems = $scope.itemDateMap[key];
for(var j=0;j<subitems.length;j++){
var item = subitems[j];
items.push(item);
}
}
return items;
}
I've updated your plnkr with my suggestion. I think it performs quite well.
Oh - I just noticed you want it sorted - I don't have time to update my example, but it is not very complicated. Use this structure instead (array with objects with arrays, instead of object with array) - this way you can use the orderBy:'date' on the root array:
[
{
date:"2013-10-05",
items: [
{
"id": 4,
"name": "oofrab",
"date": "2013-10-05 14:55:00"
},
{
"id": 3,
"name": "raboof",
"date": "2013-10-05 13:55:00"
}
]
},
{
date:"2013-10-04",
items: [
{
"id": 2,
"name": "barfoo",
"date": "2013-10-04 18:10:00"
},
{
"id": 1,
"name": "foobar",
"date": "2013-10-04 12:55:00"
}
]
}
]

How do I properly structure nested JSON values?

I have a collection of JSON values that has 3 levels:
cluster > segment > node
Where each cluster is made of segments and each segment is made up of nodes. I am trying to figure out how to represent this as a JSON object and I am unsure how to create the structure.
Each node contains an id and a reference to its segment id and cluster id. I have written up a test object like this:
var customers = [
{
"cluster" :
{"flights":4, "profit":5245, "clv":2364,
"segment" :
{ "flights":2, "profit":2150, "clv":1564,
"node" :
{ 'xpos': 1, 'ypos': 2 }// closes node
}// closes segment
}//closes cluster
},
{
"cluster" :
{"flights":4, "profit":5245, "clv":2364,
"segment" :
{ "flights":2, "profit":2150, "clv":1564,
"node" :
{ 'xpos': 1, 'ypos': 2 }// closes node
}// closes segment
}//closes cluster
}
];
The part that feels a bit flaky is the way segment and node are nested. I am not getting any errors but is this the best way to represent this data?
EDIT:
Thanks for the answers, it definitely pointed me in the right direction as far as tools to use (jsonlint) and get a better understanding of structuring data in json. They're all correct answers which shows me that it was a pretty basic question. Thanks again.
the nature of json you have is perfectly valid (the idea of an object nested in an object) if not syntactically correct (didn't verify that all your commas were in the right place).
however, you dont have what you said you wanted, which is a collection of segments in a cluster, and a collection of nodes in a segment.
change it to be
[{
"cluster": {..,
"segments": [{ <--- note the array -- you now have a collection
"name": 'segment1', <- optional, just here to show multiple segments
"nodes": [{....}] <-- same here
},
{
"name": 'segment2',
"nodes": [{....}]
}]
}
}]
I think this looks alright for the most part. However, note the following:
JSON key and values should be in double quotes"and not single quotes'. Look at yourxposandypos` values to see what I mean. I usually use JSONLint to ensure that my JSON is valid.
You say that clusters have a collection of segments and segments have a collection of nodes. This might be best represented as arrays.
It also looks like you want multiple clusters. That is also best expressed as an array.
So something of the form (greatly exaggerated the indentation, hopefully that will help):
{
"cluster" : [
{
"flights": 4,
"profit": 5245,
"clv": 2364,
"segment" : [
{
"flights": 2,
"profit": 2150,
"clv": 1564,
"node" : [
{
"xpos": 1,
"ypos": 2
},
{
//node 2
}
]
},
{
//segment 2
}
]
},
{
//next cluster
}
]
}
There is nothing wrong with the nesting, however, if each cluster can contain multiple segments, and each segment can in-turn have multiple nodes, then you ought to use an array.
{
"cluster": {
"flights": 4,
...,
"segments": [ // segments is an array
{
"flights": 6,
"nodes": [ // nodes is an array
{ "xpos": 4, "ypos": 6 },
{ "xpos": 1, "ypos": 6 },
{ third node },
...
]
},
{ second segment },
...
]
}
}
Seems fine to me, though out of habit I check everything in http://www.jsonlint.com and the slightly 'fixed' version validates (remove your single quotes and ensure you name the structure):
{
"customers": [
{
"cluster" : {
"flights": 4,
"profit": 5245,
"clv": 2364,
"segment" : {
"flights": 2,
"profit": 2150,
"clv": 1564,
"node" : {
"xpos": 1,
"ypos": 2
}
}
}
},
{
"cluster" : {
"flights": 4,
"profit": 5245,
"clv": 2364,
"segment" : {
"flights": 2,
"profit": 2150,
"clv": 1564,
"node" : {
"xpos": 1,
"ypos": 2
}
}
}
}
]
}
As a note, if you were to let jQuery or another plugin do the 'JSONification' it would turn out the same, as has also been noted, you're not representing the segments, etc as a collection (this is where I personally find building the object to be an easier representation).
.. ala (but build your object out):
var stuff = {};
stuff.customers = [];
stuff.customers[stuff.customers.length] = new Cluster();
stuff.customers[i].segment[stuff.customers[i].segment.length] = new Segment();
...etc.
...blah blah fill out object
$.toJSON('{"customerArrary":' + stuff + '}');
function cluster(){
this.flights;
this.profit;
this.clv;
this.segment = [];
}
function Segment(){
this.flights;
this.profit;
this.clv;
this.node = [];
}
function Node(){
this.xpos;
this.ypos;
}
Here's an improvement to the logic with no loss of meaning:
var customers = [
{
"ID" : "client ABC",
"cluster" : { "ID": "cluster 123", "flights": 4, "profit": 5245, "clv": 2364 },
"segment" : { "ID": "segment 456", "flights": 2, "profit": 2150, "clv": 1564 },
"node" : { "xpos" : 1, "ypos" : 2 }
}, {
"ID" : "client DEF",
"cluster" : { "ID": "cluster 789", "flights": 4, "profit": 5245, "clv": 2364 },
"segment" : { "ID": "segment 876", "flights": 2, "profit": 2150, "clv": 1564 },
"node" : { "xpos" : 1, "ypos" : 2 }
}
];
In the above, the actual 'levels' are
clusters > flights etc & segments > flights etc & nodes > xpos etc
which could also be written:
level 1: clusters
level 2: flights, profit, & clv (note: values are unique from segments tho labels are identical)
level 1: segments
level 2: flights, profit, & clv
level 1: nodes
level 2: xpos & ypos
Ok, let's agree the OP's example (as initially written) can meet the strict mechanical requirements of the JSON spec.
However, the OP describes 3 'levels', illustrating them as cluster > segment > node. The word 'level' and the arrows only make any sense if there is a semantic relationship between those objects. After all, 'levels' must relate to each other in a hierarchy, inheritance, sequence or some similarly layered fashion.
The original example gives no hint of the relationship between any part of a cluster and any part of a segment or any part of a node; it gives no way to guess what the relationship should be. The labels just sit adjacent to each other in the example, with a few extraneous braces around them.
Without an apparent relationship to encode, each of these keys most logically names a unique property of a 'customer' object--that is to say, each customer has clusters, segments and nodes. Each property is clearly labeled, and each can happily coexist in a flat structure. If OP has more info on relationships that require levels, the structure is easy to modify.
In short, nesting should have a semantic purpose; if it does not, markers of nesting should be omitted. As presented, much of the JSON syntax in the OP's example had no apparent meaning and introduces logical issues. The revision resolves these issues as well as possible with given information.

Categories