Delete JSON items based on array of allowed items - javascript

I have an array of allowedFields based on the names of the keys from a JSON array generated from a form.
A number of the retrieved fields are not required at this stage and therefore should not go through the validation process, therefore I want to match the values of the JSON array with the values of the allowedFields array
Returned JSON from form
{"reference":"sdfsdfsdfsd",
"start_date":"04/22/2014",
"end_date":"05//2014",
"status":"1","frequency":"M",
"day":"sat",
"contract_type":"S",
"notice_period":"1M"}
allowedFields = array(
reference,
start_date,
end_date,
contract_type
)
Basically I need to strip out any fields that are not listed in the allowedFields javascript array

1) Parse the JSON to an object.
var obj = JSON.parse(json);
2) Ensure that you've defined your array correctly.
var allowedFields = ['reference','start_date','end_date','contract_type'];
3) Loop over the object and if the key is not in the array delete it.
for (var k in obj) {
if (allowedFields.indexOf(k) < 0) delete obj[k];
}
4) Stringify your object back to JSON.
var str = JSON.stringify(obj);
Output
{"reference":"sdfsdfsdfsd","start_date":"04/22/2014","end_date":"05//2014","contract_type":"S"}
Fiddle

var all = {"reference":"sdfsdfsdfsd",
"status":"1"};
var allowedFields = ['reference']; // note quote marks to create strings
function filter(data, allowed) {
var filtered = {};
for(var id=0; id < allowed.length; ++id) {
var allowedField = allowed[id];
if(data.hasOwnProperty(allowedField)) {
filtered[allowedField] = data[allowedField];
}
}
return filtered;
}
console.log(filter(all, allowedFields));
>> [object Object] {
>> reference: "sdfsdfsdfsd"
>> }
Demo

underscore.js solution:
_.pick(obj,allowedFields)
http://underscorejs.org/#pick
demo
There is also _.omit(obj,string|string[]) that does the opposite.
underscore.js is extremely useful and I use it quite a bit, but you can also pick just the tools you need and include those in your code. The library is quite optimized and there is no need to write your own.
Here is the implementation (from here)
_.pick = function(obj, iterator, context) {
var result = {};
if (_.isFunction(iterator)) {
for (var key in obj) {
var value = obj[key];
if (iterator.call(context, value, key, obj)) result[key] = value;
}
} else {
var keys = concat.apply([], slice.call(arguments, 1));
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
if (key in obj) result[key] = obj[key];
}
}
return result;
};

Related

How to concatenate values of duplicate keys

When reading a csv into a javascript dictionary, how can I concatenate values of what would otherwise be duplicate keys? I've seen answers for how to do this with bash, c#, and perl, but I haven't been able to find answers for Javascript. Here's what I have:
var subjects = {};
d3.csv("test.csv", function(data) {
for (var i = 0; i < data.length; i++)
{
subjects[data[i].Id] = data[i].VALUE;
}
console.log(subjects);
});
This, obviously writes over existing keys. Instead, I want the key to be an array of the values. The csv basically looks like:
Id, VALUE
id1, subject1
id2, subject1
id1, subject3
And I want to output as:
{"id1": ["subject1", "subject3"], "id2": ["subject1"]...}
Just check if your output already has the key, if so you add the new value to the array. Else you create an array.
d3.csv("test.csv", function(data) {
var subjects = {};
for (var i = 0; i < data.length; i++)
{
// Check if key already exists
if(subjects.hasOwnProperty(data[i].Id)){
// push data to array
subjects[data[i].Id].push(data[i].VALUE);
}else{
// create new key and array
subjects[data[i].Id] = [data[i].VALUE];
}
}
console.log(subjects);
});
You could make it into an array and then push the content into that array
var subjects = {};
d3.csv("test.csv", function(data) {
for (var i = 0; i < data.length; i++)
{
//first time we see this id, turn it into an array
if(typeof subjects[data[i].Id] != "object"){
subjects[data[i].Id] = [];
}
//push content to the array
subjects[data[i].Id].push(data[i].VALUE);
}
console.log(subjects);
});
Try this inside the for loop:
typeof subjects[data[i].Id] == 'undefined' && (subjects[data[i].Id] = []);
subjects[data[i].Id].push(data[i].VALUE);
You can reduce the footprint of your code slightly if you use reduce:
var out = data.reduce((p, c) => {
const id = c.Id;
p[id] = p[id] || [];
p[id].push(c.VALUE);
return p;
}, {});
RESULT
{
"id1": [
"subject1",
"subject3"
],
"id2": [
"subject1"
]
}
DEMO

why Object.keys(data).sort() not work as expected?

I am trying to sort my object keys.
But when I'm printing my object, it always print bb first. Can anyone explain this?
It should print aa first ? I already sorted my keys.
My first key should be aa and then second should be bb.
Here is my code
var data = {
bb:"bb",
aa:"cc"
};
Object
.keys(data)
.sort();
console.log(data)
DEMO
Two things:
objects in JS have no order of elements, like arrays do
Object.keys returns an array of object keys, it does not modify the object itself, see the following example:
var data={bb:"bb",aa:"cc"};
var arr = Object.keys(data);
arr.sort();
console.log(arr); // the array IS modified,
// but it has nothing to do with the original object
try this
var data={bb:"bb",aa:"cc"};
var keys = Object.keys(data);
keys.sort();
var obj = {};
for(i = 0; i < keys.length; i++){
obj[keys[i]] = data[keys[i]];
}
console.log(obj);
There is not any method for sorting object keys in JavaScript but you can do this by a object prototype like this.
Object.prototype.sortKeys = function () {
var sorted = {},
key, a = [];
for (key in this) {
if (this.hasOwnProperty(key)) {
a.push(key);
}
}
a.sort();
for (key = 0; key < a.length; key++) {
sorted[a[key]] = this[a[key]];
}
return sorted;
}
var data = {bb: "bb", aa :"cc"};
alert(JSON.stringify(data.sortKeys())); // Returns sorted object data by their keys

Generate multi dimensional array with key value in javascript

I have an array from json like this:
{"1001":"Account1","1002":"Account2","1003":"Account3"}
and i need convert it to key value format:
[{id:"1001",name:"Account1"},
{id:"1002",name:"Account2"},
{id:"1003",name:"Account3"}]
To do this i wrote this function:
function arrayToMultiArray(list) {
var matrix = [], i;
i = -1;
for (var key in list) {
i++;
matrix[i] = [];
matrix[i].push({"id":key, "name":list[key]});
}
return matrix;
}
but the generated array has brackets for each array
[[{id:"1001",name:"Account1"}],
[{id:"1002",name:"Account2"}],
[{id:"1003",name:"Account3"}]]
How can i remove brackets of internal arrays?
You added array in array.
Just change
i++;
matrix[i] = [];
matrix[i].push({"id":key, "name":list[key]});
to
matrix.push({"id":key, "name":list[key]});
you are creating a multidimensional array.
remove this
i++;
matrix[i] = [];
and do this directly
matrix.push({"id":key, "name":list[key]});
You could do the same with Object.keys and Array.prototype.map
var obj = {"1001":"Account1","1002":"Account2","1003":"Account3"};
var arr = Object.keys(obj).map(function(key) {
return { id : key, name : obj[key] }
});
console.log(arr);

Can I simplify this Javascript loop?

I may have gone around the most convoluted way to achieve this (see code below). Could someone with experience tell me if there is a better way?
I have two JSON objects resource and data. I want to loop over each new item in data and if the key matches in resource replace the value for that key in resource with the value in data. If this does not make sense the code I have below will.
This works and does what I need it to do, but it does not feel right (don't laugh)
factory.put = function (resource, data) {
dataArr = [data];
resourceArr = [resource];
for (var i = 0; i < dataArr.length; i++) {
var obj = dataArr[i];
for (var key in obj) {
var attrName = key;
var attrValue = obj[key];
for (var i = 0; i < resourceArr.length; i++) {
var obj = resourceArr[i];
for (var key in obj) {
var resourceArrName = key;
var resourceArrValue = obj[key];
if (resourceArrName == attrName){
resource[resourceArrName] = attrValue
}
}
}
}
}
resource.put()
}
Unless I'm missing something, you have no need to stuff the objects into arrays. You just loop through the attributes of one object, data, check if that attribute exists in the other object, resource, and if it does, replace the value in resource with that of data.
for (var key in data) {
var attrName = key;
var attrValue = data[key];
if(resource[attrName]) {
resource[attrName] = attrValue;
}
}
You don't need to iterate over resourceArr's keys. Just check if resourceArr[key] exists, if so, set the value.
Something like:
if(resourceArr[key])
resourceArr[key] = attrValue;
One way to simplify the loops, is to use the forEach function, which angular provides:
factory.put = function (resource, data) {
dataArr = [data];
resourceArr = [resource];
angular.forEach(dataArr, function(obj) {
angular.forEach(obj, function(value, key) {
angular.forEach(resourceArr, function(resourceObj) {
if(resourceObj[key]) {
resourceObj[key] = value;
}
}
}
}
resource.put()
}

alphabetically sort a hash table in javascript

I am trying to sort a hashtable (originally called "resultVal") alphabetically in javascript.
// initializing an array with all the keys. //
var keys = [];
// populating it with all the keys in the hashtable. //
for (var key in resultVal) {
if (resultVal.hasOwnProperty(key)) {
keys.push(key);
}
}
// Alphabetically sorting the array populated with hash table keys. //
keys.sort();
var temp = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = resultVal[key];
if (key != "") {
temp[key].push(value);
}
}
My issue is with the last statement :-
temp[key].push(value);
What I am doing is, sort the keys alphabetically and re-feed the key and its respective values into a temp hashtable..."temp".
The push statement isn't being recognized. can anyone help?
temp is defined as an object, not an array. There's no need to push() onto it:
temp[key] = value;

Categories

Resources