Creating an efficient JSON mapping for JavaScript - 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"));

Related

Store certain values in JSON into parameters in React

brand new to Javascript.
I have figured out how to get data back from a Monday.com board, and it is returned as a JSON value like this:
{
"boards": [
{
"items": [
{
"column_values": [
{
"id": "location",
"title": "Location",
"type": "location",
"text": "Cape Town, South Africa"
}
]
},
{
"column_values": [
{
"id": "location",
"title": "Location",
"type": "location",
"text": "Paris, France"
}
]
},
{
"column_values": [
{
"id": "location",
"title": "Location",
"type": "location",
"text": "New York, NY, USA"
}
]
}
]
}
]
}
There are 3 items here, but this amount can be anything.
I need to get the location text (e.g. "Cape Town, South Africa") and then I need to use this later in an API call to get the weather of this location.
I finally managed to display in the console the location, like this:
console.log(JSON.stringify(this.state.boardData.boards[0].items[0].column_values[0].text));
Obviously this then displays what I want, but only the value of the first item.
I need to do this dynamically to get all the locations, and I need to store this into variables, so that I can then make an API call to get the weather of each of the 3 (or more) locations.
I am totally lost and have been struggling for hours. Once I manage to do this, I still have no idea how I'll make the API call but one thing at a time :)
Another approach:
const rawData = {boards:[{items:[{column_values:[{id:"location",title:"Location",type:"location",text:"Cape Town, South Africa"}]},{column_values:[{id:"location",title:"Location",type:"location",text:"Paris, France"}]},{column_values:[{id:"location",title:"Location",type:"location",text:"New York, NY, USA"}]}]}]};
const locations = [];
for (const board of rawData.boards) {
for (const item of board.items) {
for (const value of item.column_values) {
locations.push(value.text);
}
}
}
console.log(locations);
You can extract the text with some amount of nested .map. Map boards => map items => map column_values. You will get an array of arrays of arrays. And then you can apply .flat() to unwrap them all. (.flat(Infinity); also can be used)
const apiData={boards:[{items:[{column_values:[{id:"location",title:"Location",type:"location",text:"Cape Town, South Africa"}]},{column_values:[{id:"location",title:"Location",type:"location",text:"Paris, France"}]},{column_values:[{id:"location",title:"Location",type:"location",text:"New York, NY, USA"}]}]}]};
const locations = apiData.boards
.map((board) => board.items.map((i) => i.column_values.map((cv) => cv.text)))
.flat(2);
console.log(locations);
So in javascript we have an array function map, using which we can iterate over array that can be used here. It would look something like this:
let arr = boards[0].items.map(element => element.column_values[0].text)
and this arr will contain the list of all the city names, which you can further use to send the data to api.
(Edit: considering column_values to be array with one element only and items can have multiple elements)

How to access an array of objects with tooltip.format() from anychart.js

I am having trouble trying to present an array of objects on the tooltip of an Anychart.js map. I understand that we can access the dataset by doing something like: %[name of property in data set]. My data set has the following form:
{
"country": "Austria",
"id": "AT",
"continent": "Europe",
"songs": [
{
"rank": 33,
"title": "Stuck with U (with Justin Bieber)",
"artists": "Ariana Grande, Justin Bieber",
"album": "Stuck with U",
"explicit": 0,
"duration": "3:48"},
{
"rank": 34,
"title": "Late Night",
"artists": "Luciano",
"album": "Late Night",
"explicit": 0,
"duration": "3:20"
},
... more objects
]
}
}
If I wanted to access the Country property I would simply add it to the tooltip by doing:
tooltip.format("Country: " + {%country});
The issue is when trying to access an array of objects, I have tried different variations and none of them worked. Trying to show the title of every song:
tooltip.format({%songs}.{%title});
tooltip.format({%songs.%title});
tooltip.format({%songs}[{%title}]);
I also saw in the documentation that we can send a function as argument so I tried the following where I would concatenate every title of the collection but did not succeed either:
tooltip.format(function() {
let concatenated = '';
this.songs.forEach(song => {
concatenated += song + ' ';
});
return concatenated;
});
I would really appreciate your help guys.
String tokens do not support nested objects/properties. But you can use the callback function of the formatted to get access to songs. The context prototype includes getData() method provides that. Like this:
series.tooltip().format(function() {
console.log(this.getData('songs'));
return 'tooltip';
});
For details, check the live sample we prepared.
In case any one else is looking for a solution to this answer. I figured out how to loop through an embed array, and call on specific information.
chart.edges().tooltip().format(function () {
var format = ''
var songs = this.getData('songs');
songs.forEach(function (data, builtin, dom) {
format = '<p>'+data['title']+' by '+data['artists']+' </span></p>' + format
});
console.log(format)
return format
});

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;
}

Using nested mapping within Observable subscription - Angular6

I am fetching some data via an API call (within my dataservicse.ts file) - and the response I get is a sort of complex JSON structure. I am able to fetch a specific part of the response as follows in my corresponding Component file as follows -
Here is one of the JSON object response that represents the general structure -
{
"address": {
"building": "1234",
"coord": [0, 0],
"street": "123 Main Street",
"zipcode": "00000"
},
"address2": "Test Suite 000",
"grades": [{
"grade": "A",
"score": 3
}, {
"grade": "B",
"score": 4
}, {
"grade": "A",
"score": 2
}],
"name": "John Doe",
"_id": "1212121"
}
Now - my goal is to acquire the 'name' attribute as well as the first 'grade' value within the grades attribute from each response object - and map them into separate Arrays so that I can display them in table columns using *ngFor.
This is my Component code
export class TestDataComponent implements OnInit {
name$: Object;
grade$: Object;
constructor(private data: DataService, private data2: DataService) { }
ngOnInit() {
//getAPIData is returning the API response from the dataservices.ts file
this.data.getAPIData().subscribe(
data=>console.log(data.response.map(name=>name.name))
); //this works fine - I get the names in an array
this.data2.getAPIData().subscribe(
data2=>console.log((data2.response.map(grade=>grade.grades)).map(grades
=> {grades.map((value, index) => value.grade})) //this returns an undefined value
);
}
Now - if I console.log((data2.response.map(grade=>grade.grades))
I get an Array of Array objects such as -
Array - [Array(3), Array(3), Array(2)]
and each of them consist of the 'grades' attribute Array of objects.
(taking the first array from above) -
Array(3)
0:{"grade": "A","score": 3}
1:{"grade": "B", "score": 4}
2:{"grade": "A", "score": 2}
Thus - I further map my initial response to achieve the 'grade' value. Also - I only want the first grade - thus I have a simple condition added as follows -
console.log((data2.response.map(grade=>grade.grades))
.map(grades
=> {grades.map((value, index) =>{if(index<1) value.grade})}))
As mentioned in the comment - I get an undefined value.
I undestand this issue may be fairly complex but I've tried my best to explain it as clearly as possible. My goal is to get the first 'grade' values from each object and display them in an Array - just as the names, so that I can use it to display it on a table.
I am fairly new to Angular6, just switching from Angular 1.6 - so I am pretty sure I am messing something up.
What would be the best way to get the grade values into an Array by nested mapping within subscribe? Or is there a better approach to the same ?
Also - for the sake of simplicity, ignore the fact that the first subscription is present (for the name attribute) - I showed it here so as to make it clear as to what I want to achieve.
Here is what I think you're asking for since you never gave a concrete example of what you're trying to map/reduce. Also, this is vanilla JavaScript but could easily be translated into RxJS.
// I am assuming that a call to `DataServce.getAPIData()` returns an array
const api_response = [{
"address": {
"building": "1234",
"coord": [0, 0],
"street": "123 Main Street",
"zipcode": "00000"
},
"address2": "Test Suite 000",
"grades": [{
"grade": "A",
"score": 3
}, {
"grade": "B",
"score": 4
}, {
"grade": "A",
"score": 2
}],
"name": "John Doe",
"_id": "1212121"
}];
// Map and pluck the values you need
const result = api_response.map(v => [v.name, v.grades[0].score])
// Or as an array of objects
const obj_result = result.map(([name, score]) => ({ name, score }))
// Is this what you want?
console.log('Array', result);
console.log('Objects', obj_result);
Quick Update
Thanks for accepting the answer. Just wanted to give a quick of what this might look like using RxJS. I say might because the code snippet below is untested.
this.nameAndScores$ = data.getAPIData().pipe(
map(({ response }) => response),
map(({ name, grades }) => ( { name, score: grades[0].score } ))
)
Assuming that nameAndScores$ is a property of your component instance, you can do *ngFor item in nameAndScores$ | async and avoid any explicit subscriptions in your code.
You are using curly braces with a fat arrow in second map function. While using curly braces, you should return a value using the return keyword.

Add new attribute to an existing JSON inside FOR loop

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;

Categories