How to fetch json result in array using Ionic 2? - json

I am fetching data from JSON api using the below code in my 'listproduct.ts'
names = [];
this._listProduct.listProduct().subscribe(data => {
this.list = data;
console.log(data);
});
In console.log, I am fetching the result as expected, attaching a picture for your reference:
I need to fetch data.NAME in names array, how can I do this ?
data.NAME is not working.

As from the console, data is an array (of 10 elements).
When we want to convert an array to another array of the same size, 1-to-1 with some kind of "mapping", we can use the map() function.
Replace console.log(data); with this line names = data.map( e => e.NAME );
Check if it works ;)
Explanation
The function map() takes a function to be its argument, and one of the usages is to specify the element (e here) and how it corresponds to the result you want (we want e.NAME instead of the whole object e).
So e => e.NAME is a short form of e => { return e.NAME; } you may modify the function body as you might need in the future.
More information here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Related

Sorting array function over JSON loops like crazy

so I'm trying to deal with a function but it's looping like crazy and I can't figure out why.
Basically, I want to loop over a json file, retrieve every "average" value and sort it in a new array, so when I call the function ranking(countries[iso].average), it returns the position in the array.
It's actually working but the json file is way bigger, and when I console.log(rank) in the loop, it returns more than 27K messages.
ranking = (n) => {
var rank = [];
if (n) {
for (let iso in countries) {
var newvar = countries[iso].average;
rank.push(newvar);
rank.sort(function(a, b) {
return b - a;
});
}
return rank.indexOf(n) + 1
}
};
{"countries":{"US":{"name":"United States of America","ranking":"","average":13.12,"flag":"https://restcountries.eu/data/usa.svg","altNames":["US","USA"],"reports":1302,"cases":0,"deaths":299692,"recovered":23232,"lat":38,"lng":-97,"deltaCases":2,"deltaDeaths":3,"deltaRecovered":0,"casesPerOneMillion":2,"deathsPerOneMillion":903,"totalTests":22323,"testsPerOneMillion":3434,"population":345},"IN":{"name":"India","ranking":"","average":10.22,"flag":"https://restcountries.eu/data/ind.svg","altNames":["IN","Bhārat"],"reports":1016,"cases":9796992,"deaths":142222,"recovered":9290834,"lat":20,"lng":77,"deltaCases":null,"deltaDeaths":null,"deltaRecovered":646,"casesPerOneMillion":7068,"deathsPerOneMillion":103,"totalTests":151632223,"testsPerOneMillion":109402,"population":1295210000},"RU":{"name":"Russian Federation","ranking":"","average":13.21,"flag":"https://restcountries.eu/data/rus.svg","altNames":["RU","Rossiya"],"reports":1321,"cases":2597711,"deaths":45893,"recovered":2059840,"lat":60,"lng":100,"deltaCases":28585,"deltaDeaths":613,"deltaRecovered":26171,"casesPerOneMillion":17797,"deathsPerOneMillion":314,"totalTests":81564365,"testsPerOneMillion":558804,"population":146599183}}}
Thanks for any help on this
I believe that what you may be trying to do is sort by the field called average for countries in the iso. So you have some lookup called countries and there are ISOs there like I imagine: 'US'. Then Rank is an array of all these countries.
The problem I see is that you have sort happening within the for loop.
The way you explained the problem seems like 2 different steps. One retrieve the average, then AFTER that sort by the average.
If really all you want is the averages in the array: you can do like
const averages = Object.values(countries).map(country => country.average)
That single step will get you all the averages into a single array.
Then next you can sort using the same function you posted. (The key is to brake that into a second loop not a nested loop:
averages.sort((a, b) => b - a)
// now sorted
But in case you wanted to keep the rest of the data you can do that pretty easily as well:
Something more like:
const countriesSortedByAverage = Object.values(countries).sort((a, b) => b.average - a.average)
If you really need the ISO you can also do the same with Object.entries but it might be even easier to provide the iso inside the country Object.
To determine the rank for all countries you can easily add that to (if you wanted) and have that be the principal country Object:
const RANKED_LIST_OF_COUNT = countriesSortedByAverage.map((countryObj, rank) => ({ ...countryObj, rank }))
If you want to further restore it to the CountriesByISO object:
const COUNTRIES_BY_ISO_WITH_RANK = Object.assign({}, ...RANKED_LIST_OF_COUNT.map(country => ({ [country.ISO]: country}))
)

Cypress: assertion error on json field comparison

i am trying to do assertion on a json. basically i have to compare two json:
cy.get('h4#idParameters').each(($e, index, $list) => {
const text = $e.text()
expect(text).to.eq(parameters)
})
but I get the following error:
in the assertion if I use "contain" instead of "eq" the result doesn't change
There exist a space after ":" char in the first parameter. These strings are not equal.
If you want to compare this as a string, ensure it does not have extra spaces, points, or is in a different order.
But the better approach is to compare as JSON. One interesting approach should be using the deep-equal-in-any-order plugin. This plugin compares objects independent of it order. But first ensure to transform JSON strings to objects.
in the end I solved it like this. Thanks for the advice #Erme.
cy.get('h4#idParameters').each(($e, index, $list) => {
const text = $e.text()
var p1 = JSON.stringify(text)
var p2 = JSON.stringify(parameters)
p1=p1.replace(/\s/g, '');
p2=p2.replace(/\s/g, '');
p2 = p2.substr(1,p2.length)
expect(p1).to.contain(p2)
})

How to deal with Parsing Object from Join Query

I'm currently working on my first API with the Perfect framework. It's been a while since I made an API myself so I must admit my SQL and API logic is a little rusty.
I'm using a MySQL database for my implementation.
For sake of example I'll explain my database structure below;
I have a table which resembles an Object, let's call this Table A. Table A has a Varchar based id as primary key.
There are 2 other tables let's call them Table B and Table C. Table A has a one to many relation to both Table B and C. Where the id of table A is the foreign key.
What I'm trying to do is obtain everything with one query and cast it to an object in my backend.
By using outer joins I'm making the call to retrieve all the required data.
SELECT control.id, control.type, control.description, control.address, control.city, control.created, control.updated, control.latitude, control.longitude, images.id AS image_id, images.image, images.description AS image_description, updates.id AS update_id, updates.still_present, updates.created_at AS update_created
FROM Control control left outer join control_images images
ON control.id=images.control_id
left outer join Control_Updates updates
ON control.id=updates.control_id
Now is my question what would be the best way to store this data in an object that holds an array of updates and an array of images.
Before writing the join query I only attempted to get the values from Table A I used the following code to cast the results to my desired object.
let result = mysql.storeResults()
let checkResult = self.checkResult(result: result, response: response)
response = checkResult.response
var controls: [Control] = []
while let row = result?.next() {
let type = Types(rawValue: row[1].unwrap)!
let control = Control(id: row[0].unwrap, type: type, description: row[2].unwrap, address: row[3].unwrap, city: row[4].unwrap, latitude: Double(row[7].unwrap).unwrap, longitude: Double(row[8].unwrap).unwrap)
controls.append(control)
}
obviously this will just return duplicate objects apart from the images and updates of course.
I'm wondering if this is the best way to do it or if I should call a new query in the while loop
The best way to resolve this issue, by still only using one query and one loop is by using 'hashmaps'. I'm not familiar with Perfect framework, but in PHP it would look something like:
// Get results from the db:
$results = $db->execute($query, $params);
// Define map for controls:
$map = [];
// Loop over results/rows
foreach($results as $row){
// Get unique identifier for the Control model:
$controlId = $row['id'];
// Check if control is NOT already in map:
if(!isset($map[$controlId]){
// Add control to map:
$control = [
'id' => $controlId,
'description' => $row['description'],
'images' => []
// other fields
];
// Add control to map:
$map[$controlId] = $control;
}
else{
// Control exists, retrieve it from the map:
$control = $map[$controlId];
}
// Retrieve unique identifier of the image:
$imageId = $row['image_id'];
// Same tactic with hasmap, check if control already has the image, if not add it
if(!isset($control['images'][$imageId]){
// add the image to the hashmap:
}
else{
// Image is already added, the content from the 'update' data is not added yet, handle that part (also with a hash map)
}
}
Hope that helps you figure it out in Perfect framework

How to satisfy the lint rules 'array-callback-return'?

This is my first cut:
const planLimits = {plan1: {condition1: 50, ...}}
function initialisePlanLimits(planLimits) {
const limits = new Map();
Object.keys(planLimits).map((planId) => (
const limitMap = new Map(Object.entries(planLimits[planId]));
limits.set(planId, limitMap);
));
return limits;
}
The linter flags this error: error Expected to return a value in this function array-callback-return
So I changed to this version:
function initialisePlanLimits(planLimits) {
const limits = new Map();
Object.keys(planLimits).map((planId) => (
limits.set(planId, new Map(Object.entries(planLimits[planId])))
));
return limits;
}
It throws another error Unexpected parentheses around single function argument having a body with no curly braces arrow-parens
My questions:
1) I reckon I can fix my first version by sticking in a return null within the curry bracket. But is there a better, more elegant way? A bogus return statement does not make sense in this context
2) Why the second version fails? Isn't it equivalent to the first version?
If I use forEach instead of map, it will not cause the array-callback-return lint error
Object.keys(planLimits).forEach((planId) => (
const limitMap = new Map(Object.entries(planLimits[planId]));
limits.set(planId, limitMap);
));
Well, accepted answer advocates about using 'forEach,' which is true. Please read below explaination from ESLint documentation,
Array has several methods for filtering, mapping, and folding. If we forget to write return statement in a callback of those, it's probably a mistake. If you don't want to use a return or don't need the returned results, consider using .forEach instead.
TLDR: ESLint and Function Return Values
This issue is caused by not returning a value when using map(), see how the results are expected according to the docs...
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array. (Source: MDN WebDocs.)
Demonstration of Issue in JavaScript
With this code sample of JS, which shows a group of elements...
var newarray = [];
array.map( (item, index) => {
newarray.push('<li>' + item + '</li>');
});
I get this error...
Expected to return a value in arrow function array-callback-return
The error goes away if I add a single return to the above function, like so :
var newarray = array.map( (item, index) => {
return '<li>' + item + '</li>';
});
`map()` - So why should I use it?
You can clearly see elsewhere, too, on MDN Docs, that what is returned is, "A new array with each element being the result of the [return value of the] callback function." So, if you are using map(), it's also a very good idea to also use return returnvalue!
map() is a powerful tool. Don't throw that tool away.

How to make a query in MongoDB using a JSON?

is there anyway to make a query in MongoDB using a JSON and returning a object if one field of the json matches with some in the database?
for example, I have the this object called keysArray
{ house: 'true', garden: 'false' }
and I would like to make a query in Mongo passing this object as a query field and return if some object in my database matches with at least one of those fields :
keysArray.forEach(function(key){
collection.find({keysArray}, function(err, propertyMatch){
console.log(propertyMatch)
})
})
I got no objects back, even if I have one object in my database that matches these fields.
Thanks in advance
...and I would like to make a query in Mongo passing this object as a
query field and return if some object in my database matches with at
least one of those fields.
It sounds like OR logic - if I understood it well.
On this specific case it's not possible to pass in JSON-like object to query as it would be a implicit AND logic condition.
So you should build first a OR expression and use it in collection.find(), something like this:
var myjson = {'status': 32, 'profile': {$exists: false}};
function build_logic_or(json) {
var orExpr = [];
for (var field in json) {
var expr = {};
expr[field] = json[field];
orExpr.push(expr);
}
return {'$or': orExpr};
}
It would build an expression like this:
{"$or":[{"status":32},{"profile":{"$exists":false}}]}
So:
db.collection.find(build_logic_or(myjson))