I have this code below that takes items of a PC and returns a quote, price etc. As of now, the only way that I can add or remove components is by directly modifying the array. Here is the code
class PriceCalc {
Motherboard = 520.99;
RAM = 250.4;
SSD = 500.8;
HDD = 400.66;
Case = 375.5;
Monitor = 600.75;
Keyboard = 100.99;
Mouse = 25.5;
constructor(Obj) {
this.parts = Obj;
this.cost = "$" + Obj.reduce((a, b) => a + this[b], 0).toFixed(2);
this.retail = "$" + (Obj.reduce((a, b) => a + this[b], 0) + Obj.reduce((a, b) => a + this[b], 0) * 1.75).toFixed(2);
this.quote = "Your quote is " + this.retail;
}
}
This is the key values
quote = new PriceCalc(["Motherboard", "RAM", "SSD", "HDD", "Case", "Monitor", "Keyboard", "Mouse"]);
console.log(quote.parts);
console.log(quote.cost);
console.log(quote.retail);
console.log(quote.quote);
What Id like to implement is a code as shown below that I can add within the class and call it to add new parts to the quote or remove existing parts.
function removePart(arr, part) {
return arr.filter(function (ele) {
return ele != part;
});
} var result = removePart(["Motherboard", "RAM", "SSD", "HDD", "Case", "Monitor", "Keyboard", "Mouse"], "Mouse");
console.log(result)
I would like to implement it in a way where I can call this.parts (as stated in the previous code) and either call a new function that pushes new parts to "parts" or call a new function that removes certain parts that are already in the list. I hope what I've described makes sense
Here is s a general example template of what I mean, without the functional code:
class quote {
constructor(/*...*/) {
this.parts = ....
}
add() {
//adds item
}
remove() {
//removes item
}
}
example = new quote(["part1", "part2"])
add(part3)
console.log(example) //returns ["part1" "part2" "part3"]
remove(part1)
console.log(example) //returns ["part2" "part3"]
This should work
class quote {
constructor(initialParts) {
this.parts = initialParts
}
add(part) {
this.parts = [...this.parts, part]
}
remove(part) {
this.parts = this.parts.filter( p => p !== part)
}
}
example = new quote(["part1", "part2"])
example.add('part3')
console.log(example) //returns ["part1" "part2" "part3"]
example.remove('part1')
console.log(example) //returns ["part2" "part3"]
If you want multiple of the same item you can still use an object and store the key as the name of the product and the number of items as the value. simply adjust the functions to account for this.
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 am trying to find out some elegant solution how to merge values of object's properties if the name is same.
Example:
var object = {
"10-10-2017": "Black friday",
"11-09-2017": "Some holiday",
"10-10-2017": "Fathers day"
}
Merge to:
var object = {
"10-10-2017": "Black friday Fathers day",
"11-09-2017": "Some holiday",
}
I use this object as a feed for calendar where property name is date and property value is/are events for the date and my solution cannot handle two properties with the same name. This feed is generated by template engine and it cannot can only render it this way (for each context of an event it adds a line to the object) when a view is rendered.
For those who know Kentico CMS I am using repeater with effect to build this object, where " var object = {" is html envelope before and "} " is html envelope after.
For the first edit I suggest that you change your object into other form
from
var object = {
"10-10-2017": "Black friday",
"11-09-2017": "Some holiday",
"10-10-2017": "Fathers day"
}
to
var object =[
{"date":"10-10-2017","value":"Black friday"},
{"date":"11-09-2017","value":"Some holiday"},
{"date":"10-10-2017","value":"Fathers day"}
]
If that helps you here's the working solution
var object = [{date:"10-10-2017",value:"Black friday"},{date:"11-09-2017",value:"Some holiday"},{date:"10-10-2017",value:"Fathers day"}];
var output =[];
object.forEach(function(value) {
var existing = output.filter(function(v, i) {
return v.date == value.date;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
output[existingIndex].value += ' '+value.value
} else {
if (typeof value.value == 'string')
value.value = value.value;
output.push(value);
}
});
console.log(JSON.stringify(output)); //returns [{"date":"10-10-2017","value":"Black friday Fathers day"},{"date":"11-09-2017","value":"Some holiday"}]
In case the question from my comment answers with Yes, this possibly provides a working approach ...
// BEGIN of CMS templating ...
var descriptorList = [];
// programmatically push into a list of property descriptors,
// each descriptor holding just one key value pair.
// +++ BEGIN iteration here ...
descriptorList.push({ "10-10-2017": "Black friday" });
// ...
// ... keep looping ... "Kentico CMS repeater"?
// for the sake of providing a working example
// there will be some more descriptors pushed ...
descriptorList.push({ "11-09-2017": "Some holiday" });
descriptorList.push({ "10-10-2017": "Fathers day" });
// ... END of iteration. +++
function mergeObjectsAndConcatSamePropertyStringTypes(a, b) {
var
type = Object.assign({}, a, b); // - start with a raw merged type (merger).
Object.keys(b).filter(function (key) { // - collect `key` duplicates.
return (key in a);
}).forEach(function (key) { // - for each duplicate `key` that targets
var aValue = a[key]; // a string type at each object, do concat
var bValue = b[key]; // this values and assign it to the merger.
if ((typeof aValue == 'string') &&/*||*/ (typeof bValue == 'string')) {
type[key] = [aValue, bValue].join(' ');
}
});
return type;
}
// assembling of the desired type ...
var type = descriptorList.reduce(mergeObjectsAndConcatSamePropertyStringTypes, {});
// END of CMS templating ...
console.log('descriptorList : ', descriptorList);
console.log('type : ', type);
.as-console-wrapper { max-height: 100%!important; top: 0; }
First of all your code is not correct as JS will only picks up the last prop if name is same.
> var object = {
... "10-10-2017": "Black friday",
... "11-09-2017": "Some holiday",
... "10-10-2017": "Fathers day"
... }
undefined
> object
{ '10-10-2017': 'Fathers day', '11-09-2017': 'Some holiday' }
>
But
For the extra prop, there is an solution, hope this helps you, e.g. your
object[newProperty] = (object[newProperty] || '') + newValue;
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);
Currently solving a puzzle and looking for some tips on sorting by events ordered. I would like to know what exactly is the procedure I should be following. Consider this
I input a number, then there n inputs
each input has two events, where of for event1 event2, and event1 happens before event2.
Consider the input
6
Eatfood Cuthair
Eatfood BrushTeeth
School EatFood
School DoHair
DoHair Meeting
Meeting Brushteeth
The output will be
school -> dohair-> eatfood -> meeting -> cuthair -> brushteeth
In that order. Since if we write everything down, school is indeed the first thing that occurs, and then dohair is second. If more than one possible ordering exists simply output one. You may assume that all events are connected in some way, and no circular dependencies exist.
What I am thinking about doing is making two arrays, one which has all eventOne's and all eventTwo's. I'm not really sure where to go from here though. I would like to do this in javascript. Thanks! Any hints or algorithms are suggested
Another Input
6
vote_140_prof announce_140_prof
vote_140_prof first_day_of_classes
dev_shed_algo vote_140_prof
dev_shed_algo do_hair
do_hair big_meeting
big_meeting first_day_of_classes
Output
dev_shed_algo do_hair vote_140_prof big_meeting announce_140_prof first_day_of_classes
I found the solution file on my computer, its in python which I don't know, but hopefully this will help others understand the problem
from collections import defaultdict
def toposort(graph, roots):
res = [i for i in roots]
queue = [i for i in roots]
while queue:
for i in graph[queue.pop(0)]:
if i not in res:
res.append(i)
queue.append(i)
return res
graph = defaultdict(set)
a_set = set()
b_set = set()
for i in range(int(input())):
a, b = input().split()
a_set.add(a)
b_set.add(b)
graph[a].add(b)
print(" ".join(i for i in toposort(graph, a_set - b_set)))
My attempt
var words =
'vote_140_prof announce_140_prof vote_140_prof first_day_of_classes devshed_algo vote_140_prof dev_shed_algo do_hair do_hair big_meeting big_meeting first_day_of_classes';
var events = words;
events = events.split(/\s+/);
console.log(events);
var obj = {};
for (var i = 0 ; i < events.length ; i++)
{
var name = events[i];
if(obj[name] === undefined )
{
obj[name] = [];
}
obj[name].push(events[i%2 === 1 ? i-1 : i+1]);
}
console.log(obj);
FORMATING
function sequenceEvents(pairs){
var edges = pairs.reduce(function(edges,pair){
edges.set(pair[0],[]).set(pair[1],[]);
new Map();
});
pairs.forEach(function(edges,pair){
edges.set(pair[0],[]).set(pair[1],[]);
});
var result = [];
while(edges.size){
var children = new Set([].concat.apply([],[...edges.value()]));
var roots = [...edges.keys()].filter(function(event){
!children.has(event);
});
if(!roots.length) throw "Cycle detected";
roots.forEach(function(root){
result.push(root);
edges.delete(root);
});
}
return result;
}
The Python algorithm is not correct. It will fail for this input:
3
A B
A C
C B
It will output:
A, B, C
...which conflicts with the last rule. This is because it wrongly assumes that the children of any root-event can be safely added to the result, and depend on no other events. In the above case, it will identify A as root, and B and C as its children. Then it will pop of C from that list, and add it to the result, without seeing that C depends on B, which is not in the result yet.
As others have noted, you need to make sure the capitalisation is consistent. Brushteeth and BrushTeeth are considered different events. The same is true for EatFood and Eatfood.
I provide here a solution. I hope the inline comments explain well enough what is happening:
function sequenceEvents(pairs) {
// Create a Map with a key for each(!) event,
// and add an empty array as value for each of them.
var edges = pairs.reduce(
// Set both the left and right event in the Map
// (duplicates get overwritten)
(edges, pair) => edges.set(pair[0], []).set(pair[1], []),
new Map() // Start with an empty Map
);
// Then add the children (dependent events) to those arrays:
pairs.forEach( pair => edges.get(pair[0]).push(pair[1]) );
var result = [];
// While there are still edges...
while (edges.size) {
// Get the end points of the edges into a Set
var children = new Set( [].concat.apply([], [...edges.values()]) );
// Identify the parents, which are not children, as roots
var roots = [...edges.keys()].filter( event => !children.has(event) );
// As we still have edges, we must find at least one root among them.
if (!roots.length) throw "Cycle detected";
roots.forEach(root => {
// Add the new roots to the result, all events they depend on
// are already in the result:
result.push(root);
// Delete the edges that start with these events, since the
// dependency they express has been fulfilled:
edges.delete(root);
});
}
return result;
}
// I/O
var input = document.querySelector('#input');
var go = document.querySelector('#go');
var output = document.querySelector('#output');
go.onclick = function() {
// Get lines from input, ignoring the initial number
// ... then split those lines in pairs, resulting in
// an array of pairs of events
var pairs = input.value.trim().split(/\n/).slice(1)
.map(line => line.split(/\s+/));
var sequence = sequenceEvents(pairs);
output.textContent = sequence.join(', ');
}
Input:<br>
<textarea id="input" rows=7>6
EatFood CutHair
EatFood BrushTeeth
School EatFood
School DoHair
DoHair Meeting
Meeting BrushTeeth
</textarea>
<button id="go">Sequence Events</button>
<div id="output"></div>
Without arrow functions nor apply
As in comments you indicated you like to have the code without arrow functions first:
function sequenceEvents(pairs) {
// Create a Map with a key for each(!) event,
// and add an empty array as value for each of them.
var edges = pairs.reduce(function (edges, pair) {
// Set both the left and right event in the Map
// (duplicates get overwritten)
return edges.set(pair[0], []).set(pair[1], []);
}, new Map() ); // Start with an empty Map
// Then add the children (dependent events) to those arrays:
pairs.forEach(function (pair) {
edges.get(pair[0]).push(pair[1]);
});
var result = [];
// While there are still edges...
while (edges.size) {
// Get the end points of the edges into a Set
var children = new Set(
[...edges.values()].reduce(function (children, value) {
return children.concat(value);
}, [] )
);
// Identify the parents, which are not children, as roots
var roots = [...edges.keys()].filter(function (event) {
return !children.has(event);
});
if (!roots.length) throw "Cycle detected";
roots.forEach(function (root) {
// Add the new roots to the result, all events they depend on
// are already in the result:
result.push(root);
// Delete the edges that start with these events, since the
// dependency they express has been fulfilled:
edges.delete(root);
});
}
return result;
}
Okay. Here's my shot at the problem.
var makePair = function(i0, i1) {
return {start: i0, end: i1};
};
var mp = makePair;
var makeBefores = function(pairs) {
var befores = {};
pairs.forEach(function(pair) {
if (befores[pair.end] == null) {
befores[pair.end] = [pair.start];
} else {
befores[pair.end].push(pair.start);
}
if (befores[pair.start] == null) {
befores[pair.start] = [];
}
});
for (var key in befores) {
console.log("after " + key + "there is:");
for (var i = 0; i < befores[key].length; i++) {
console.log(befores[key][i]);
}
}
return befores;
};
var shouldGoBefore = function(item, before) {
for (var i = 0; i < before.length; i++) {
if (item == before[i]) {
return true;
}
}
return false;
};
var sortEvents = function(pairs) {
if (pairs.length === 0) {
return [];
}
if (pairs.length === 1) {
return [pairs[0].start, pairs[0].end];
}
console.log(pairs);
var befores = makeBefores(pairs);
var sorted = [];
for (var key in befores) {
var added = false;
for (var i = 0; i < sorted.length; i++) {
console.log('checking if ' + sorted[i] + ' should go before ' + befores[key]);
if (shouldGoBefore(sorted[i], befores[key])) {
//console.log("splicing");
sorted.splice(i, 0, key);
added = true;
break;
}
}
if (!added) {
sorted.push(key);
}
}
return sorted.reverse();
}
var pairs = [mp('vote_140_prof','announce_140_prof'),mp('vote_140_prof','first_day_of_classes'),mp('dev_shed_algo','vote_140_prof'),mp('dev_shed_algo','do_hair'),mp('do_hair','big_meeting'),mp('big_meeting','first_day_of_classes'),mp('announce_140_prof','first_day_of_classes')];
console.log(sortEvents(pairs));
One reason things may not have been working is your test data had inconsistent capitalization. The results of this run are:
Array [ "School", "EatFood", "CutHair", "Meeting", "BrushTeeth", "DoHair" ]
I'm going to test it on your other data set but I believe this fulfills the prompt. I'm going to write up how it works in a minute.
Note that this doesn't do any file IO or reading of lines. It takes the input to sortEvents as an array of objects that have a start and end property, which I provided a helper method makePair to create.
The solution works by building a dictionary of what elements go before which others.
If you had an input like:
a->b
c->a
c->b
b->d
The dictionary would be like this:
a->[c],
c->[],
b->[a,c],
d->[b]
Then we use an array as a sort of linked list and we go through it seeing whether we have to insert something. So for example, if we are trying to see where a should be inserted and the list is c, then we would look at the dictionary for c, see that c is in it and then we know that before a there is supposed to be c, therefore we have to insert a after c
Take a hash map start with first event and put it's value to 0 than whenever you encounter event 2 check the value of event 1 in hash than put a smaller value for event 2. Once complete sort hash by value.
Bingo
line = input();
myMap = dict()
i=0
while i < line:
event1 = raw_input()
event2 = raw_input()
if event1 in myMap :
myMap[event2] = myMap[event1]+1
elif event2 in myMap:
myMap[event1] = myMap[event2]-1
else :
myMap[event1] = 0
myMap[event2] = 1
i=i+1
print i
print myMap
I don't know why some people downvoted but yes it's working, Atleast on both your samples
Sample input and output
6
eatfood
cuthair
1
{'eatfood': 0, 'cuthair': 1}
eatfood
brushteeth
2
{'brushteeth': 1, 'eatfood': 0, 'cuthair': 1}
school
eatfood
3
{'brushteeth': 1, 'eatfood': 0, 'school': -1, 'cuthair': 1}
school
dohair
4
{'brushteeth': 1, 'eatfood': 0, 'school': -1, 'cuthair': 1, 'dohair': 0}
dohair
meeting
5
{'school': -1, 'brushteeth': 1, 'cuthair': 1, 'dohair': 0, 'eatfood': 0, 'meeting': 1}
meeting
brushteeth
6
{'school': -1, 'brushteeth': 2, 'cuthair': 1, 'dohair': 0, 'eatfood': 0, 'meeting': 1}
The code is in python, feel free to convert in javascript
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));