Validating values in YAML files across collection - javascript

I'm using Node (https://eemeli.org/yaml/) to parse a YAML configuration files which looks like so:
items:
- name: item 1
value: 25
- name: item 2
value: 25
- name: item 3
value: 50
What I'd like to do is assert the value numbers all add up to 100 when parsing the document.
Should I be running this validation after parsing the YAML
eg:
data = YAML.parse(recipe)
validate(data)
Or is there a better way of doing this using the YAML library directly when loading the document?
Thanks in advance for your help!

You're better of parsing the YAML first, then going through the resulting data. So, in this case, the parsed data would look something like:
data = {
items: [
{name: 'item 1', value: 25},
{name: 'item 2', value: 25},
...
]
}
So, you can just loop through the values:
let total = 0;
data.items.map((item) => {
total += item.value;
});
if (total !== 100) {
...
}

Related

Read XLSX to from the update query

I am using XLSX NPM to read the XLSX file and i converted to json as like below
My Xlsx sheet is of format:..
skill id name xx
abc 4578 express-basic 30
4698 express-advanced 60
qwerty 7856 express-basic 90
MY Json:
[ { skill: 'abc',
id: 4578,
name: 'express-basic',
xx: 30 },
{ id: 4689, name: 'express-advanced', xx: 60 },
{ skill: 'qwerty',
id: 7856,
name: 'express-advanced',
xx: 90 } ]
I have to update collection X where id=4578,4689 ass skill = abc so how can i convert the below json into as follows:
[
{'abc':[4578,4689]},
{'qwerty':[7856]}
]
so that i can loop through this and i can update the collectionX. My problem is how can i know the next skill is starting from the json and construct the Above array. Thanks...
You Can work with array.reduce.
YOUR_JSON_ARRAY.reduce(function (obj, item) {
obj[item.skill] = obj[item.skill] || [];
obj[item.skill].push(item.id);
return obj;
}, {});
Above code will groupBy your Array by using item.skill key.
P.S. you need to handle this if item.skill doesn't exists,
otherwise it will create undefined key:value pair.
Hope it will help.

Javascript object as a type of mini database?

Is it possible to use a JavaScript object as a type of mini database? I often find myself needing a kind of database structure when I'm coding in JS but it feels like overkill to use an actual database like MySQL (or similar).
As an example, let's say I need to structure this data as a JS object:
Object idea: Stuff to sell
Items to sell: The junk in the garage
Object structure: List all items including item name, item condition, and item value
In order to make this into a JS object I would maybe write:
var stuffToSell = {};
Then my first item would maybe look like:
var stuffToSell = {
item : "Coffee Maker",
condition : "Good",
price : 5
};
Now to me this seems like I'm on the right track, until I come to add another item and I end up having to use the properties item, condition, and price again in the same JS object — which feels wrong? — or is it?? At this point my brain keeps shouting the word "ARRAY!" at me but I just can't see how I can use an array inside the object, or an object inside an array to achieve what I want.
My end goal (in this simplified example) is to be able to then use object-oriented syntax to be able to access certain items and find out specific information about the item such as price, condition etc. For example if I want to know the price of the "coffee maker" I would like to write something like:
stuffToSell["coffee maker"].price
...and then the result above should be 5.
I feel like I'm on the right track but I think I'm missing the array part? Could someone please tell me what I'm missing or maybe what I'm doing completely wrong! And also if it is wrong to have duplicate property names in the same JS object? For example, is it okay to have:
var stuffToSell = {
item : "Coffee Maker",
price : 5,
item : "Mountain Bike",
price : 10,
item : "26 inch TV",
price : 15
};
...it seems wrong because then how does JS know which price goes with which item??
Thanks in advance :)
You're definitely on the right track!
A lot of people will refer to what you're talking about as a hash.
Here's my suggested structure for you:
var store = {
coffee_maker: {
id: 'coffee_maker',
description: "The last coffee maker you'll ever need!",
price: 5,
},
mountain_bike: {
id: 'mountain_bike',
description: 'The fastest mountain bike around!',
price: 10,
},
tv: {
id: 'tv',
description: 'A big 26 inch TV',
price: 15,
},
}
Having a structure like that will let you do this:
store.mountain_bike.price // gives me 10
Need an array instead, say for filtering or looping over?
Object.keys gives you an Array of all the object's keys in the store ['coffee_maker', 'mountain_bike', 'tv']
// Now we just have an array of objects
// [{id: 'coffee_maker', price: 5}, {id: 'mountain_bike', price: 10} ...etc]
var arr = Object.keys(store).map(el => store[el])
Need to just filter for items that are less than 10?
This will give us an array of products less than 10:
// gives us [{id: 'coffee_maker', price: 5}]
var productsUnder10 = arr.filter(el => el.price < 10)
These techniques can be chained:
var productsOver10 = Object.keys(store)
.map(el => store[el])
.filter(el => el.price > 10)
Need to add a product?
store['new_product'] = {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
Here's another way, which would be good to start getting used to.
This is a 'safe' way to update the store, read up on immutability in javascript to learn about it
store = Object.assign({}, store, {
'new_product': {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
})
...and another way, that you should also read up on and start using:
This is the object spread operator, basically just an easier way to work with immutable structures
store = {
...store,
'new_product': {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
}
Resources
JavaScript Arrow Functions
Object and Array Spread Syntax
Immutable Javascript using ES6 and beyond
You can actually use json or create an array of objects.If using a separate file to store the objects, first load the file. Use array filter method to get an new array which matches the filter condition , like you want to get the item with id 1. This will return an array of objects.
var dict = [{
'id': 1,
'name': 'coffee-mug',
'price': 60
},
{
'id': 2,
'name': 'pen',
'price': 2
}
]
function getItemPrice(itemId) {
var getItem = dict.filter(function(item) {
return item.id === itemId
});
return getItem[0].price;
}
console.log(getItemPrice(1))
JSON objects don't support repeated keys, so you need to set unique keys.
Put an id as your key to group your items:
var stuffToSell = {
'1': {
item: "Coffee Maker",
price: 5
},
'2': {
item: "Mountain Bike",
price: 10
}
.
.
.
}
Now you can access the item's price very fast.
Look at this code snippet (Known Ids)
var stuffToSell = {
'1': {
item: "Coffee Maker",
price: 5
},
'2': {
item: "Mountain Bike",
price: 10
},
'3': {
item: "26 inch TV",
price: 15
}
};
let getPrice = (id) => stuffToSell[id].price;
console.log(getPrice('1'));
See? the access to your items it's fast and your code follows a readable structure.
Look at this code snippet (Item's name as key)
var stuffToSell = {
'Coffee Maker': {
price: 5
},
'Mountain Bike': {
price: 10
},
'26 inch TV': {
price: 15
}
};
let getPrice = (id) => stuffToSell[id].price;
console.log(getPrice('Coffee Maker'));
Look at this code snippet (Item's name: price)
var stuffToSell = {
'Coffee Maker': 5,
'Mountain Bike': 10,
'26 inch TV': 15
};
let getPrice = (id) => stuffToSell[id];
console.log(getPrice('Coffee Maker'));

can I filter a countBy in lodash?

For a list like (with many many entries):
-
id: cs13157
name: 'Current Load'
-
id: cs1085
name: 'Check CPU'
-
id: cs1070
name: Uptime
-
id: cs1070
name: 'Total Processes'
I've got a .countBy for ids that is returning some counts that are greater than 1 and some equal to 1. I only care about the greater than 1 values, since that indicates a problem. But since countBy is returning a big object, I have to loop the hash table values:
counts = ld(list).countBy('id').value();
for (k in counts) {
v = counts[k];
if (!(v > 1)) {
continue;
}
logger.error("found duplicate value for ID " + k);
errored = true;
}
// throw if errored is true
This seems a like too much code but I can't see a way to quickly do this with lodash. I could pluck/map/filter to find the errant values. There's plenty of ways to do this but I'm wondering if there's a way to only get the list of IDs with a count greater than one with lodash and not with a loop.
SSCE:
var arr, keys, ld, s;
s = "- {id: 2240errorapp, name: 'app error count'}\n- {id: 2240errorinf, name: 'infrastructure error count'}\n- {id: '2112', name: calls}\n- {id: '2112', name: calls}\n- {id: 2112v, name: violations}\n- {id: 2112avg, name: 'average response time'}\n- {id: 2112errorapp, name: 'app error count'}\n- {id: 2112errorinf, name: 'infrastructure error count'}";
ld = require('lodash');
arr = (require('yamljs')).parse(s);
keys = ld(arr).countBy('id').filter(function(k, v) {
return k[v] > 1;
}).value();
console.dir(keys);
Expected value: ['2112'] (the duplicate). Actual value: [].
counts.pick(function(v) { return v > 1; });
pick, not filter. Also v > 1 not k[v] > 1 as in your code.
filter wants an array of objects, not an object with many uniform keys. pick likes to work with object properties and filter out keys.
My answer is a duplicate of this question but I wouldn't recommend closing this question since there's more than one way to solve this problem.

How to access a specific index of an array in node.js

I want to get only the AID from the solution now i am getting. I tried rows[0] but was not successful.
Code:
console.log('The solution is: ', rows);
Output:
The solution is:
[ { AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89 } ]
Use rows[0]["AID"] to access the AID property.
Let's understand your overall data structure here:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
The variable rows is an array of objects. Thus rows[n] gets you a specified object in that array and therefore rows[0] is the first object in the array which would be:
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
So, now you want to access the AID property in that object so you can just do:
rows[0].AID
And, here's a working snippet demo:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
document.write(rows[0].AID);

JSON / Jade - Cannot output JSON variable to Jade template

I'm passing some JSON data to a Jade template, but can't seem to print the JSON data to my Jade template. This is an example of the JSON which is stored and passed to the Jade template:
{ name: 'Team 1',
_id: 5134d71192cf972226000003,
__v: 0,
key: 1362417425623 }
It is passed through to the Jade template like so:
res.render('tournamentDetails', { 'tournamentData' : tournamentData, seedsSerialized : JSON.stringify(tournamentData.teams) } );
The format of the Jade template is:
script(type='text/javascript')
var seeds = [#{tournamentData.teams}];
I'm trying to access this variable seeds in a seperate JavaScript file, but cannot seem to access them. I have been testing using alert to test what is in seeds in the JavaScript file and it is not the teams.
This is the generated HTML from the Jade too:
var seeds = [{ name: 'Team 1',
_id: 5134d71192cf972226000003,
__v: 0,
key: 1362417425623 },{ name: 'Team 2',
_id: 5139dc66b48da58d0e000001,
__v: 0,
key: 1362746470498 },{ name: 'Team 3',
_id: 5139dda45f1598440f000001,
__v: 0,
key: 1362746788314 },{ name: 'Team 4',
_id: 513b2c66cfd50dce11000001,
__v: 0,
key: 1362832486554 }];
How would I access the teams in a JavaScript file? I am wanting to output the names of the teams to the Jade template.
This may not be an answer exactly, but it was too long for a comment...
Look at this jsfiddle: http://jsfiddle.net/KvXTA/
var seeds = [{ name: 'Team 1',
_id: 5134d71192cf972226000003,
__v: 0,
key: 1362417425623 },{ name: 'Team 2',
_id: 5139dc66b48da58d0e000001,
__v: 0,
key: 1362746470498 },{ name: 'Team 3',
_id: 5139dda45f1598440f000001,
__v: 0,
key: 1362746788314 },{ name: 'Team 4',
_id: 513b2c66cfd50dce11000001,
__v: 0,
key: 1362832486554 }];
console.log(seeds);
notice how the console outputs
Uncaught SyntaxError: Unexpected token ILLEGAL
That's because of the _id fields. I'm surprised you say that the serialized version has the same problem, since it should have surrounded the ID's in quotes. If you don't need the ID's at all, you can get rid of them in the serialized version by using a replacer function.
var seedsSerialized = JSON.stringify(teams, function (key, val) {
return key === '_id' ? undefined : val;
);
res.render('tournamentDetails', { seedsSerialized: seedsSerialized });
Then use that serialized version to initialize seeds in the template.
script
var seeds = !{seedsSerialized};
My earlier comment about order of including scripts wasn't a concern that maybe another file was creating a seeds variable, it was that you might have been including a file which used seeds before seeds was actually declared.
For example:
<script src='logSeeds.js'></script>
<script>
var seeds = [ ... ];
</script>
where logSeeds.js is:
console.log(seeds);
would obviously output undefined since seeds hasn't been declared yet. It was just a thought, not necessarily your situation.

Categories

Resources