I am just wondering if there is an easy way to create an associative object from a string that needs double split, thisstring is the result from an api call, so length of the object could change.
For instance, if I have a string that looks like this:
var infoValue = 'Loan Date~Loan Number~Loan Amount|15/03/2016~1042~620|15/03/2016~1044~372';
I want to have an object that looks like this:
[
{
"Loan Date":"15/03/2016",
"Loan Number":"1042",
"Loan Amount":"620",
},
{
"Loan Date":"15/03/2016",
"Loan Number":"1042",
"Loan Amount":"620",
}
]
What I am doing right now is something like
var res = infoValue.split("|");
var activeLoans = new Array();
for(field in res) {
if(res[field] != ''){
activeLoans.push(res[field]);
}
}
for(field in activeLoans){
var row = activeLoans[field];
rowSplit = row.split("~");
}
But I am not happy with this approach, as I need to create a table to display this data, and the site that I am getting this api might change the order of the response of the string, or might add other values
What you have done is about all you can do, though I would not use for..in for a typical array. You should be able to deal with any sequence of values, as long as the header is consistent with the rest of the data, e.g.
var infoValue = 'Loan Date~Loan Number~Loan Amount|15/03/2016~1042~620|15/03/2016~1044~372';
function parseInfoValue(s) {
var b = s.split('|');
var header = b.shift().split('~');
return b.reduce(function(acc, data) {
var c = data.split('~');
var obj = {};
c.forEach(function(value, i){
obj[header[i]] = value;
})
acc.push(obj);
return acc;
},[]);
}
var x = parseInfoValue(infoValue);
document.write(JSON.stringify(x));
This will create the required structure no matter how many items are in each record, it just needs a label for each item in the header part and a value for each item (perhaps empty) in every data part.
Edit
Thinking on it a bit more, I don't know why I used forEach internally when reduce is the obvious candidate:
var infoValue = 'Loan Date~Loan Number~Loan Amount|15/03/2016~1042~620|15/03/2016~1044~372';
function parseInfoValue(s) {
var b = s.split('|');
var header = b.shift().split('~');
return b.reduce(function(acc, data) {
acc.push(data.split('~').reduce(function(obj, value, i) {
obj[header[i]] = value;
return obj;
}, {}));
return acc;
}, []);
}
var x = parseInfoValue(infoValue);
document.write(JSON.stringify(x));
Related
I have a URL with query params that looks something like this
&rootDimension=availability%253AOnlinepipsymbBrand%253ADell%253ABICpipsymbProduct%2520Rating%254A3%2520stars%2520and%2520above
I am doing a decodeURIComponent(query.rootRootdimension).split("pipsymb") which returns an array that looks like this
["availability:Online", "Brand:Dell:BIC", "Product Rating:4 stars and above"]
I basically need to check the array and remove keys that aren't "Brand" or "Product Rating". So in this case it should return an array ["Brand:Dell:BIC", "Product Rating:4 stars and above"].
If the product rating is "4 stars and above" should replace it with "Top Rated" if not it should just keep the rating for example ["Brand:Dell:Bic", "Product Rating: "3 stars and above"]. The array should then look like this
["Brand:Dell:BIC", "Product Rating:Top Rated"].
The result I am looking for is ["Dell", "Bic", "Top Rated"]
I tried the function below and a few other things but I didn't get what I was looking. Thanks for the help/suggestions!
const getRefinements = (query) => {
decodeURIComponent(query.rootDimension).split("pipsymb").reduce((obj, str) => {
let strParts = str.split(/::|:/);
if (strParts[0] && strParts[1]) {
obj[strParts[0].replace(/\s+/g, "")] = strParts[1];
return Object.values(pick(obj, ["Brand", "ProductRating"]))
}
})
}
Try following:
let query = decodeURIComponent(
"&rootDimension=availability%253AOnlinepipsymbBrand%253ADell%253ABICpipsymbProduct%2520Rating%254A3%2520stars%2520and%2520above"
);
query = query
.replace(/%3A/g, ":")
.replace(/%20/g, " ")
.replace(/%4A/g, "J");
const productDetails = query.split("pipsymb");
let brandPart = productDetails
.find(item => item.match("Brand"))
.replace("Brand:", "")
.split(":");
let productRating = productDetails
.find(item => item.match("Product Rating"))
.split("J")[1];
if (productRating.includes("4")) {
productRating = "Top Rated";
}
const result = [...brandPart, productRating];
console.log(result);
Output
['Dell', 'BIC', '3 stars and above']
If you have control over the URL, you should split the things you want to get into &availability=Online&brand=Dell,BIC&productRating=4 stars and above
This was you'll be able to split it a bit better without having to remove extra strings, using something like the already provided URLSearchParams function.
let queryString = `&availability=Online&brand=Dell,BIC&productRating=4 stars and above`,
urlParams = new URLSearchParams(queryString),
results = {},
arr = [];
urlParams.forEach((v,k) => {
if (k === "productRating") {
if (v === "4 stars and above") {
results.rating = "Top Rated";
} else {
results.rating = v;
}
} else if (k === "brand") {
results.brands = v.split(","); // replace with ":" if delimiter cannot be changed
}
});
// this should be what you get
// results = {
// rating : "Top Rated",
// brands : ["Dell", "BIC"]
// }
// this will give you what you originally wanted, but it's not a very good data structure, use results instead if possible
arr = results.brands.concat(results.rating);
I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};
I am attempting to extract JSON values (from structure called jsonWithListOfStatesAndCounters) if it matches with an element in my inputted array (inputedJurisdictionArray). My inputed array contains sting values that include singular or multiple state names (i.e. var inputedJurisdictionArray = ["Iowa", "California, Indiana, Delaware", "Florida"]). The singular State values in this array are handled normally at the end, but the multiple state values is where it gets tricky. I am using split() in order to turn them into another array so they can get processed one by one. Anytime one of the states from this inputed array matches with a "state" value in jsonWithListOfStatesAndCounters, I am extracting it into another JSON structure and pushing it at the end of every block into my initial variable myJurisdictionJSON. The problem I am having is that once these forEach loops are completed, I am still left with my original values in myJurisdictionJSON, instead of the val and counter that should be extracted. The jsonWithListOfStatesAndCounters definitely contains the values that should match with the elements of my inputedJurisdictionArray, but the information is not being pushed into myJurisdictionJSON. What am I doing wrong? Any tips/pointers will be helpful.
var myJurisdictionJSON = [{
jurisdiction_val: 'jurisdiction_val',
jurisdiction_counter: 'jurisdiction_counter'
}];
inputedJurisdictionArray.forEach(function each(item) {
if (Array.isArray(item)) {
item.forEach(each);
} else {
var jurisdictionInput = item;
jsonWithListOfStatesAndCounters.forEach(function each(item) {
if (Array.isArray(item)) {
item.forEach(each);
} else {
if (jurisdictionInput.includes(",") === true){//Checking if more than one jurisdiction in string
var jurisdictionArr = jurisdictionInput.split(", ");
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
jurisdictionArr.forEach(function(element) {
if (myJurisdictionJSON.jurisdiction_counter == 'jurisdiction_counter'){ // If nothing is pushed into our predefined JSON object
if (jurisdictionState.toLowerCase() == trim(element.toLowerCase())) {
var jurisdictionJSON_inner = {
jurisdiction_val: element,
jurisdiction_counter: jurisdictionCounter
};
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}else if (myJurisdictionJSON.jurisdiction_counter != 'jurisdiction_counter'){ // if an item has been pushed into myJurisdictionJSON, append the next items
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
if (jurisdictionState.toLowerCase() == trim(jurisdictionInput.toLowerCase())) {
jurisdictionJSON_inner.jurisdiction_val = jurisdictionJSON_inner.jurisdiction_val + ", " + jurisdictionInput;
jurisdictionJSON_inner.jurisdiction_counter = jurisdictionJSON_inner.jurisdiction_counter + ", " + jurisdictionCounter;
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}
});
}
else{// if only one jurisdiction state in jurisdictionInput string
var jurisdictionCounter = item.jurisdictionCounter;
var jurisdictionState = item.jurisdictionState;
if (jurisdictionState.toLowerCase() == trim(jurisdictionInput.toLowerCase())) {
var jurisdictionJSON_inner = {
jurisdiction_val: jurisdictionInput,
jurisdiction_counter: jurisdictionCounter
};
myJurisdictionJSON.push(jurisdictionJSON_inner);
return;
}
}
}
});
I'm not totally sure the output is what you want but it's close.
// input data as per your example
let inputedJurisdictionArray = [
'Iowa',
'California, Indiana, Delaware',
'Florida'
];
// I had to make this part up. It's missing from the example
let jsonWithListOfStatesAndCounters = [{
jurisdictionCounter: 2,
jurisdictionState: 'Florida'
},
{
jurisdictionCounter: 4,
jurisdictionState: 'Indiana'
},
{
jurisdictionCounter: 3,
jurisdictionState: 'Texas'
}
];
// first, fix up inputedJurisdictionArray
// reduce() loops over each array element
// in this case we're actually returning a LARGER
// array instead of a reduced on but this method works
// There's a few things going on here. We split, the current element
// on the ','. Taht gives us an array. We call map() on it.
// this also loops over each value of the array and returns an
// array of the same length. So on each loop, trim() the whitespace
// Then make the accumulator concatenate the current array.
// Fat arrow ( => ) functions return the results when it's one statement.
inputedJurisdictionArray = inputedJurisdictionArray.reduce(
(acc, curr) => acc.concat(curr.split(',').map(el => el.trim())), []
);
// now we can filter() jsonWithListOfStatesAndCounters. Loop through
// each element. If its jurisdictionState property happens to be in
// the inputedJurisdictionArray array, then add it to the
// myJurisdictionJSON array.
let myJurisdictionJSON = jsonWithListOfStatesAndCounters.filter(el =>
inputedJurisdictionArray['includes'](el.jurisdictionState)
);
console.log(myJurisdictionJSON);
In my app I've got 2 functions to work with localStorage.
When I add the first and second items, it works properly, but when it is the third item, it gives an error.
Here are the functions:
w.getLocalStorage = function() {
var c = localStorage.getItem('cities');
var arr = [];
arr.push(c);
return c ? arr : [];
}
w.setLocalStorage = function(data, googleData, cities, name) {
if (data) {
city.name = data.name;
city.coord.lat = data.coord.lat;
city.coord.lon = data.coord.lon;
cities.push(JSON.stringify(city));
// console.log(city);
localStorage.setItem("cities", cities);
} else if (googleData) {
city.name = name;
city.coord.lat = googleData.results[0].geometry.location.lat;
city.coord.lon = googleData.results[0].geometry.location.lng;
console.log('cities', cities);
cities.push(JSON.stringify(city));
// console.log(cities, city);
localStorage.setItem("cities", cities);
}
}
Here is what it returns for the first 2 items:
Array[1]
0 : "{"name":"Pushcha-Voditsa","coord":{"lat":50.45,"lon":30.5}}"
1 : "{"name":"Kyiv","coord":{"lat":50.4501,"lon":30.5234}}"
Here is what when the third items is added:
Array[1]
0 : "{"name":"Pushcha-Voditsa","coord":{"lat":50.45,"lon":30.5}}, {"name":"Kyiv","coord":{"lat":50.4501,"lon":30.5234}}"
1 : "{"name":"Kyiv","coord":{"lat":50.4501,"lon":30.5234}}"
How can I fix this?
As you can only store string in localStorage, to persist object convert them in stringified format using JSON.stringify() method and on retrieval use JSON.parse() to parses the JSON string to construct the JavaScript value or object.
Here are the code snippet, which require attention. You should persist stringified cities data
cities.push(city);
localStorage.setItem("cities", JSON.stringify(cities));
While retrieval, parse it JavaScript object
var cities = localStorage.getItem('cities');
var c = cities ? JSON.parse(cities) || [];
My Json is like this:
[
{"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
]
I want all the names which have BankOut value as "Y" into an array using JavaScript, in order to use those names in my protractor automation.
You need to use filter method of array. It takes function as it argument. And runs it against each element of array. If function returns true (or other truthy value) then that element stays in newly created array.
var list =[ {"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso ", "CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
];
var onlyBankOutY = list.filter(function (item) {
return item.BankOut === 'Y';
});
document.body.innerHTML = onlyBankOutY.map(function (item) {
return JSON.stringify(item);
}).join('<br>');
var list =[
{"isoCode":"BW","name":"Botswana ","CashOut":"Y","BankOut":"","MMT":null},
{"isoCode":"BR","name":"Brazil ","CashOut":"Y","BankOut":"Y","MMT":null},
{"isoCode":"BG","name":"Bulgaria ","CashOut":"Y","BankOut":"Y","MMT":"Y"},
{"isoCode":"BF","name":"Burkina Faso ", "CashOut":"Y","BankOut":"","MMT":null}, {"isoCode":"BI","name":"Burundi","CashOut":"","BankOut":"","MMT":"Y"},
{"isoCode":"KH","name":"Cambodia","CashOut":"Y","BankOut":"","MMT":null}
];
var names = [];
list.forEach(function(el) {
if (el.BankOut === 'Y') {
names.push(el.name)
}
})