excluding "missing" values in reductio.avg() - javascript

I was hoping to use reductio to compute averages within my crossfilter groups. My dataset includes missing values (represented by null) that I'd like to exclude when calculating the average. However, I don't see a way to tell reductio to exclude certain values, and it treats the null values as 0.
I wrote a custom reduce function to accomplish this without using reductio:
function reduceAvg(attr) {
return {
init: function() {
return {
count: 0,
sum: 0,
avg: 0
};
},
add: function(reduction, record) {
if (record[attr] !== null) {
reduction.count += 1;
reduction.sum += record[attr];
if (reduction.count > 0) {
reduction.avg = reduction.sum / reduction.count;
}
else {
reduction.avg = 0;
}
}
return reduction;
},
remove: function(reduction, record) {
if (record[attr] !== null) {
reduction.count -= 1;
reduction.sum -= record[attr];
if (reduction.count > 0) {
reduction.avg = reduction.sum / reduction.count;
}
else {
reduction.avg = 0;
}
}
return reduction;
}
};
}
Is there a way to do this using reductio? Maybe using exception aggregation? I haven't fully wrapped my head around how exceptions work in reductio.

I think you should be able to average over 'myAttr' excluding null and undefined by doing:
reductio()
.filter(function(d) { return d[myAttr] !== null && d[myAttr] !== undefined; })
.avg(function(d) { return d[myAttr]; });
If that doesn't work as expected, please file an issue as it is a bug.

Related

Check array elements and see if it contains flag my loops are not working

Trying to find out that if member of rxDetails contain combination inside rxInfos of flags based on that increment counter in below scenario it should retVlaue false because logic of for of loop should be at member level not the complete rxDetails object. what is implemented wrong any help ?
main.js
const rxDetails = [
{"member": 1 , "rxInfos":[
{ "firstFillIndicator": "Y",
"acceptDigitalFirstFill": "Y" },
{ "firstFillIndicator": "Y",
"acceptDigitalFirstFill": "Y" },
]},
{"member": 2 , "rxInfos":[
{ "firstFillIndicator": "N",
"acceptDigitalFirstFill": "Y" },
{ "firstFillIndicator": "N",
"acceptDigitalFirstFill": "Y" },
]},
]
function validateOrderRequest(rxDetails) {
let retVlaue = false;
let firstFillCounter = 0;
let refillCounter = 0;
for (const member of rxDetails) {
for (const rx of member.rxInfos) {
if (rx.firstFillIndicator === "Y" && rx.acceptDigitalFirstFill === "Y") {
firstFillCounter++;
} else {
refillCounter++;
}
}
if (refillCounter > 0 && firstFillCounter > 0) {
retVlaue = true;
return retVlaue;
} else {
retVlaue = false;
}
}
return retVlaue;
}
console.log(validateOrderRequest(rxDetails));
You want to return true if for any given element in the array, the element has:
At least one combination of "Y", "Y"
At least one other combination
Your problem is that your counter is running from the start to the end of the outer array. Instead, you should move the declarations inside the first for loop.
Alternatively, you can simplify this a bit by using the some array function for your loops.
validateOrderRequest(rxDetails) {
return rxDetails.some(member => {
let firstFillCounter = 0;
let refillCounter = 0;
for (let i = 0; i < member.rxInfos.length; i++) {
const rx = member.rxInfos[i];
if (rx.firstFillIndicator === "Y" &&
rx.acceptDigitalFirstFill === "Y") {
firstFillCounter++;
} else {
refillCounter++;
}
if (firstFillCounter > 0 && refillCounter > 0) {
return true;
}
}
return false;
});
}
some will return true for the first element it finds for the condition in the callback.
In this example, the inner loop returns true if a member has at least one "Y", "Y" combination and at least one !"Y", !"Y" combination.
The outer some returns true if at least one member satisfies this condition.
DEMO: https://stackblitz.com/edit/angular-read7t
The following part looks suspicious, why would you return upon meeting one condition and not the other? Remember returning stops the execution of the rest of the script
if (refillCounter > 0 && firstFillCounter > 0) {
retVlaue = true;
return retVlaue;
} else {
retVlaue = false;
}

Middle element in stack

I read the article on stack implementation in javascript and python on geeksforgeeks website. I implemented the code to delete the middle element in the stack in javascript exactly as given for python in the same website. But I get wrong answer. Why is it so? what is the difference between the two languages in this case? How can I get the correct answer in javascript? Below is the code in Javascript.
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
}
function deleteMid(stack, curr) {
// If stack is empty or all items
// are traversed
if (stack.isEmpty() || curr == stack.items.length) {
return;
}
// Remove last item
x = stack.peek();
stack.pop();
// Remove other items
deleteMid(stack, curr + 1);
console.log("length value: ", stack.items.length);
// Put all items back except middle
if (curr != Math.floor(stack.length / 2)) {
stack.push(x);
}
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, 0);
stack.print();
There are some parts of the Python implementation that your implementation misses:
You have an implicitly global x variable - unlike Python, in Javascript, variables declared without var / let / const are assigned to the global object, so once the recursive deleteMids have completed, there's only been one variable named x (rather than one for each iteration) which you've reassigned every time. Use const x instead, to ensure that every call of deleteMid has its own binding of x.
Your stack does not have a length property, so your curr != Math.floor(stack.length/2) test results in curr != NaN - which isn't what you want. Although you could give your stack a length getter property:
get length() {
return this.items.length;
}
this still does not conform to the Python implementation, which continually recursively passes the initial length, as another argument: if you want to imitate the Python implementation, do this too, with an n variable:
function deleteMid(stack, n, curr) {
// ...
// Remove other items
deleteMid(stack, n, curr + 1);
// Put all items back except middle
if (curr != Math.floor(n / 2)) {
// ...
// Call with:
deleteMid(stack, stack.items.length, 0);
The problem with checking the length property is that it will change while you're iterating, which will make things much more difficult to work with.
For the same reason, so that even sized stacks work, we also need to change your JS test here:
if (stack.isEmpty() || curr == stack.items.length) {
to correspond to the Python code:
if (st.isEmpty() or curr == n) :
Working code:
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
get length() {
return this.items.length;
}
}
function deleteMid(stack, n, curr) {
// If stack is empty or all items
// are traversed
if (stack.isEmpty() || curr === n) {
return;
}
// Remove last item
const x = stack.peek();
stack.pop();
// Remove other items
deleteMid(stack, n, curr + 1);
// Put all items back except middle
if (curr != Math.floor((n) / 2)) {
stack.push(x);
}
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack, stack.items.length, 0);
stack.print();
Since you know the middle index when you start, you can check the stack's length after each item's removal, and stop when you hit the middle.
class Stack {
constructor() {
this.items = [];
}
push(element) {
this.items.push(element);
}
pop() {
if (this.items.length === 0) {
return "Underflow";
} else {
return this.items.pop();
}
}
peek() {
return this.items[this.items.length - 1];
}
isEmpty() {
return this.items.length == 0;
}
print() {
console.log(this.items);
}
}
function deleteMid(stack, middle = Math.round(stack.items.length / 2)) {
if (stack.isEmpty()) return;
const isMiddle = stack.items.length === middle;
// Remove last item
const x = stack.pop();
// stop when you get to the middle
if (isMiddle) return;
// Remove other items
deleteMid(stack, middle);
// add the item back
stack.push(x);
}
var stack = new Stack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.print();
deleteMid(stack);
stack.print();

How can I make a large if/else statement tighter?

I have something like the following:
if (value === section1) {
runChecks(checkObject[1].value1, checkObject[1].value2, leftAlign);
} else if (value === section2) {
runChecks(checkObject[2].value1, checkObject[2].value2, rightAlign);
} else if (value === section3) {
runChecks(checkObject[3].value1, checkObject[3].value2, leftAlign);
} else if (value === section4) {
runChecks(checkObject[4].value1, checkObject[4].value2, rightAlign);
} else if (value === section5) {
runChecks(checkObject[5].value1, checkObject[5].value2, leftAlign, true);
} else if (value === section6) {
runChecks(checkObject[6].value1, checkObject[6].value2, rightAlign);
} ...
It runs longer than this as there's a large number of pre-defined values.
Example of checkObject:
var checkObject = [{
value1: '19.1%',
value2: '19.1%',
}, {
value1: '19.1%',
value2: '19.1%',
}, {
value1: '19.1%',
value2: '19.1%',
}, ...
I want to break it down and make it more efficient but given there's variations on the data being passed to runChecks() I'm not sure how to manage it.
Use switch!
switch(value){
case section1:
runChecks(checkObject[1].value1, checkObject[1].value2, leftAlign);
break
case section2:
runChecks(checkObject[2].value1, checkObject[2].value2, rightAlign);
break
...
}
It's not really any shorter than using if / else if / else but it looks cleaner.
Actually, you can just use a for loop.
Create an array object containing all the sections. (I will provide the real javascript later. But here is some half-pseudocode).
var counter = 1;
var N = something;
var sectionArray = {section1, section2, section3, ..., sectionN};
for(;counter<N; counter++){
if(value === sectionArray[counter]){
runChecks(checkObject[counter].value1, checkObject[counter].value2, rightAlign);
break;
}
}
One way would be to use loop for instance.
let sections = ['section1', 'section2', 'section3', 'section4'];
for (let i = 0; i < sections.length; i++) {
if (value === sections[i]) {
runChecks(checkObject[1].value1, checkObject[1].value2, leftAlign);
}
}
You could use some with a short circuit if the value is found.
[section1, section2, section3, section4, section5, section6].some((v, i) => {
if (v === value) {
runChecks(
checkObject[i + 1].value1,
checkObject[i + 1].value2,
i % 2 ? rightAlign : leftAlign
i === 5 || undefined
);
return true;
}
});
Couldn't you iterate over the array? You might need to add all information that you require in the runChecks function though (I added mybool, since I wasn't sure where this true is coming from).
checkObject.forEach(function(value, index) {
let alignment = index % 2 == 0 ? leftAlign : rightAlign;
runChecks(value.value1, value.value2, alignment, value.mybool);
});
There are too many repeating parts in your code. I would do it this way.
var scs = [null, section1, section2, section3, section4, section5, section6];
var si = scs.indexOf(value);
var align = ((si&1)==1) ? leftAlign : rightAlign;
runChecks(checkObject[si].value1, checkObject[si].value2, align, si==5);

Find maximum sum path through binary tree - javascript

I've been trying to figure this problem out for a couple days and can't seem to optimize the solution to make it tenable.
I have a tree that's 100 levels deep, so brute force (2^100 possible combinations?) is obviously not working..
Here is the code I have so far:
// Node constructor | structure of nodes
var Node = function(val) {
this.val = Number(val);
this.left = null;
this.right = null;
}
function maxPathUtil(top, store) {
if (top === null || top === undefined) return 0;
if (top.left === null && top.right === null) {
// console.log("hello");
return top.val;
}
leftSub = maxPathUtil(top.left, store);
rightSub = maxPathUtil(top.right, store);
store[0] = Math.max(store[0], leftSub+rightSub+top.val);
return Math.max(leftSub, rightSub) + top.val;
}
function maxPathSum(top) {
store = [];
store[0] = 0;
maxPathUtil(top, store)
return store[0];
}
var top = nodify(levels);
console.log(maxPathSum(top));
Is there a way to memoize this solution / otherwise improve the big O or is that as efficient as it gets?
So, each node should have ab additional extra property, let's call it "currLength"
When you parse the text file and you add the nodes to the tree, then you need to set the this value to the currLength of the parent node + the value of the current node.
After this you only need to check the bottom nodes of the tree to get the lengths of each path.
If you want to optimize this further, then you can add a currMaxLength variable to the tree, set it to -Infinity initially, and when you add a node with a higher currLength, then you set currMaxLength to currLength.
Keep in mind, this doesn't make it any faster, this just moves the compexity to the init part. It works like insertion sort.
here's how I've solved this problem in JavaScript, hope it helps!
var hasPathSum = function(root, sum) {
if (root == null) {
return false
}
var result = checkTree(root,root.val,sum)
console.log(result)
return result
};
function checkTree(node,currentSum,sum) {
if (currentSum == sum && node.left == null && node.right == null) {
return true
}
var result = false
if (node.left != null) {
result = result || checkTree(node.left,currentSum+node.left.val,sum)
}
if (node.right != null) {
result = result || checkTree(node.right,currentSum+node.right.val,sum)
}
return result
}
also on my Github
function pathSum(root , sum){
//Add Base Case For Recursion
if(root === null)return false;
//Add another base case
if(root.val === sum &&(root.left === null && root.right === null)return true
// here when it reach to the leaf where the next is null for both left and right
return pathSum(root.left , sum - root.val)|| pathSum(root.right ,sum - root.val )
//So In the code above I added (||) because If the first recursion return false, it will execute next recursion and so on
}

How to handle extremely large data in node.js array

I am working on a Node.js server that responds with JSON. I have a legacy server that contains the data. The Node.js server acts as a middle-man connecting the user to the data. The legacy server returns data as a csv with columns being keys and rows being objects. I want to turn this into an array of json objects. I am using this tool to do just that: https://github.com/Keyang/node-csvtojson. I can either have the tool construct the output for me or I can have a function called with each row passed in and construct it myself. I am currently doing the later.
The users of my application can pass in a search value which means only rows that contain this value should be returned. The user can also pass in filter keys and values which means only rows where key contains value for every key and value given should be returned. They can of course give both search and filter values or neither. They also give a sort key which is the key in the objects to sort the array by. They also give me a sort order: ascending or descending. They also give me a page size and offset to return, which is for pagination.
My question is, what is the best way to handle this with data sets that could contain millions of rows? I can't modify the legacy server. Here is what I have. It works but I would like to improve performance as much as possible. Is there a more efficient way to do the sorting, searching, filtering, pagination, etc? Would it be better to add to the array and then sort instead of using a binary search tree and sorting during add? Is there a way I could use streams to improve performance? I expect the server to be limited by CPU performance not RAM. I am looking for any recomendations for better performance. Thanks! :)
EDIT: Also, what part of the below code is blocking?
function searchRow(row, search) {
if (search) {
for (var key in row) {
if (row.hasOwnProperty(key) && row[key].toString().toLowerCase().indexOf(search.toLowerCase()) > -1) {
return true;
}
}
return false;
} else {
return true;
}
}
function filterByField(obj) {
return obj.field === this.valueOf();
}
function filterRow(row, filter) {
if (filter) {
filter = JSON.parse(decodeURIComponent(filter));
var passed = true;
for (var key in filter) {
if (filter.hasOwnProperty(key)) {
var index = row[key].toString().toLowerCase().indexOf(filter[key].toString().toLowerCase());
passed = passed && (index > -1);
}
if (!passed) {
break;
}
}
return passed;
} else {
return true;
}
}
function orderByKey(key, reverse, a, b) {
return function (a, b) {
var x = (a[key] || '').toString().toLowerCase();
var y = (b[key] || '').toString().toLowerCase();
if (x > y) {
return reverse ? -1 : 1;
} else if (y > x) {
return reverse ? 1 : -1;
} else if (hash(a) > hash(b)) {
return reverse ? -1 : 1;
} else if (hash(b) > hash(a)) {
return reverse ? 1 : -1;
} else {
return 0;
}
};
}
function sortedInsert(element, array, key, reverse) {
array.splice(locationOf(element, array, key, reverse) + 1, 0, element);
return array;
}
function locationOf(element, array, key, reverse, start, end) {
if (array.length === 0) {
return -1;
}
start = start || 0;
end = end || array.length;
var pivot = parseInt(start + (end - start) / 2, 10);
var c = orderByKey(key, reverse, element, array[pivot]);
if (end - start <= 1) {
return c == -1 ? pivot - 1 : pivot;
}
switch (c) {
case -1: return locationOf(element, array, key, reverse, start, pivot);
case 0: return pivot;
case 1: return locationOf(element, array, key, reverse, pivot, end);
}
}
function getTable(path, columns, delimiter, query) {
var deferred = q.defer();
var headers = [];
var data = [];
delimiter = delimiter ? delimiter : '\t';
var converter = new Converter({
delimiter: delimiter,
noheader: true,
headers: columns,
workerNum: os.cpus().length,
constructResult: false
});
converter.on("error", function(errMsg, errData) {
deferred.reject(errMsg);
});
converter.on("record_parsed", function(row) {
if (searchRow(row, query.search) && filterRow(row, query.filter)) {
sortedInsert(row, data, query.sort || headers[0].split("!").pop(), query.order === 'desc');
}
});
converter.on("end_parsed", function() {
var offset = parseInt(query.offset || 0);
var limit = parseInt(query.limit || data.length);
var total = data.length;
data = data.slice(offset, offset + limit);
deferred.resolve({
"total": total,
"rows": data
});
});
var options = {
url: config.url + path,
gzip: true,
method: 'GET'
};
request(options, function (error, response, body) {
if (error || response.statusCode != 200) {
deferred.reject(error);
}
}).pipe(converter);
return deferred.promise;
}

Categories

Resources