Sorting JSON Object via JavaScript odd results - javascript

Alright Odd results, not so much as they are expected. However I'm not sure how to over come it, I am having one of those days where every logical thing is the equivalent of a massive brain fart for me. Anyway. Lets say for the sake of ease. My array is numeric only nothing else in there.. My array ranges from 1-50 so my results upon sorting it are similar to 1, 10, 11, 12, 13.... 2, 20, 21, 22, 23... etc. When I need it to go like 1,2,3,4,5,6,7,8,9,10,11,12...
My simple little canned function is..
function sortJSONresultsByWidgetID(a,b)
{
if(parseInt(a.wigetID) == parseInt(b.wigetID))
{
return 0;
}
return parseInt(a.wigetID) > parseInt(b.wigetID) ? 1 : -1;
}
for reference I parseInt due to the JSON the way my JSON handles when I post it back and forth from the DB, I store the actual JSON in the DB and when passing it to the PHP it wraps quotes around the number turning them from INT to string (or from what I notice that may be browser based).
So here I am stuck now cause I want these things listed in a particular order and my brain wont work today.
EDIT example of me sorting results:
dashboardJSON.widgets.sort(sortJSONresultsByWidgetID);

You need to parse the ints with a radix of 10 and use the === operator instead of ==. I think that should do it.
function sortJSONresultsByWidgetID(a,b)
{
var widgetAId = parseInt(a.wigetID, 10);
var widgetBId = parseInt(b.wigetID, 10);
if(widgetAId === widgetBId)
{
return 0;
}
return widgetAId > widgetBId ? 1 : -1;
}
UPDATE - Here's with Ellian's optimization:
function sortJSONresultsByWidgetID(a,b)
{
return parseInt(a.wigetID, 10) - parseInt(b.wigetID, 10);
}

Related

Practicing arrays and loops in JS and can't get my int -> binary project to work

I know there's like 8 line solutions to convert integers to binary, but I'm trying my hand at creating a little program that does the same thing with arrays. I'm using 3 arrays, the first stores the original number to be converted and all the values of dividing that number by 2 and then rounding down when there's a remainder, aka [122, 61, 61, 30.5, 30, 15.5, 15, etc. etc.], and the second array will store the binary digits based on if remainder of division is true || false, aka [0,1,0,1,1,1,1]. Not yet written, but at the end I'll take the binaryArray and reverse and toString it to get 1111010, the correct binary for 211.
Obviously I'm doing more than one thing wrong, but I'm getting close as I can see the correct initial results when I console.log the main function. Any help here is appreciated, except I don't need to know how to do this entire concept easier, as I've already studied the easier solutions and am attempting this on purpose for practice.
Run the code snippet to see that the output is close to the solution, but obviously lastNumArray is not being updated and the entire thing is not looping.
let num = 122;
let array = [num];
let binaryArray = [];
let lastNumArray = array[array.length - 1];
function convertToBinary(number) {
let lastNumArray = number;
var result = (number - Math.floor(number)) !== 0;
if (result) {
binaryArray.push('1') &&
array.push(lastNumArray / 2) &&
array.push(Math.floor(array[array.length - 1]))
} else {
binaryArray.push('0') &&
array.push(lastNumArray / 2) && //this pushes 61
array.push(Math.floor(array[array.length - 1]))
}
}
while (array > 1) {
convertToBinary(lastNumArray) &&
lastNumArray.push(array[array.length - 1])
}
console.log(array)
console.log(binaryArray)
console.log(lastNumArray)
Any help or pointers here would be much appreciated. I've tried for loops, do while loops, and more and I'm getting close, but I really want to find out what I'm doing wrong here so I can learn. This is the first little function I've tried to write solo, and it's definitely keeping me humble!
You could try something like that with recursive call
let results = []
let binary = []
function cb(number) {
if (number === 0) return
results.push(number)
results.push(number / 2)
results.push(Math.floor(number / 2))
const last_index = results.length - 1
if (results[last_index] === results[last_index - 1]) {
binary.push("0")
} else {
binary.push("1")
}
cb(results[last_index])
}
cb(122)
console.log(results)
console.log(binary)
console.log(binary.reverse().join(""))

what is the equivalent of a reduce in javascript

I'm a backend dev moved recently onto js side. I was going through a tutorial and came across the below piece of code.
clickCreate: function(component, event, helper) {
var validExpense = component.find('expenseform').reduce(function (validSoFar, inputCmp) {
// Displays error messages for invalid fields
inputCmp.showHelpMessageIfInvalid();
return validSoFar && inputCmp.get('v.validity').valid;
}, true);
// If we pass error checking, do some real work
if(validExpense){
// Create the new expense
var newExpense = component.get("v.newExpense");
console.log("Create expense: " + JSON.stringify(newExpense));
helper.createExpense(component, newExpense);
}
}
Here I tried to understand a lot on what's happening, there is something called reduce and another thing named validSoFar. I'm unable to understand what's happening under the hood. :-(
I do get the regular loops stuff as done in Java.
Can someone please shower some light on what's happening here. I should be using this a lot in my regular work.
Thanks
The reduce function here is iterating through each input component of the expense form and incrementally mapping to a boolean. If you have say three inputs each with a true validity, the reduce function would return:
true && true where the first true is the initial value passed into reduce.
true && true and where the first true here is the result of the previous result.
true && true
At the end of the reduction, you're left with a single boolean representing the validity of the entire, where by that if just a single input component's validity is false, the entire reduction will amount to false. This is because validSoFar keeps track of the overall validity and is mutated by returning the compound of the whether the form is valid so far and the validity of the current input in iteration.
This is a reasonable equivalent:
var validExpense = true;
var inputCmps = component.find('expenseform')
for (var i = 0; i < inputCmps.length; i++) {
// Displays error messages for invalid fields
inputCmp.showHelpMessageIfInvalid();
if (!inputCmp.get('v.validity').valid) {
validExpense = false;
}
}
// Now we can use validExpense
This is a somewhat strange use of reduce, to be honest, because it does more than simply reducing a list to a single value. It also produces side effects (presumably) in the call to showHelpMessageIfInvalid().
The idea of reduce is simple. Given a list of values that you want to fold down one at a time into a single value (of the same or any other type), you supply a function that takes the current folded value and the next list value and returns a new folded value, and you supply an initial folded value, and reduce combines them by calling the function with each successive list value and the current folded value.
So, for instance,
var items = [
{name: 'foo', price: 7, quantity: 3},
{name: 'bar', price: 5, quantity: 5},
{name: 'baz', price: 19, quantity: 1}
]
const totalPrice = items.reduce(
(total, item) => total + item.price * item.quantity, // folding function
0 // initial value
); //=> 65
It does not make sense to use reduce there and have side effects in the reduce. Better use Array.prototype.filter to get all invalid expense items.
Then use Array.prototype.forEach to produce side effect(s) for each invalid item. You can then check the length of invalid expense items array to see it your input was valid:
function(component, event, helper) {
var invalidExpenses = component.find('expenseform').filter(
function(ex){
//return not valid (!valid)
return !ex.get('v.validity').valid
}
);
invalidExpenses.forEach(
//use forEach if you need a side effect for each thing
function(ex){
ex.showHelpMessageIfInvalid();
}
);
// If we pass error checking, do some real work
if(invalidExpenses.length===0){//no invalid expense items
// Create the new expense
var newExpense = component.get("v.newExpense");
console.log("Create expense: " + JSON.stringify(newExpense));
helper.createExpense(component, newExpense);
}
}
The mdn documentation for Array.prototype.reduce has a good description and examples on how to use it.
It should take an array of things and return one other thing (can be different type of thing). But you won't find any examples there where side effects are initiated in the reducer function.

sorting two associative arrays/stacks

I am implementing an algorithm I designed and am exploring different approaches
This isn't a homework problem but I am going to explain it like one: lets say a merchant has bought inventory of apples on different days, and also sold some on different days. I want the weighted average timestamp of their current purchases.
I am storing this data object as timestamp string in epoch time, and quantity of apples. My dataset actually has the purchases and the sells in separate data sets, like so:
//buys
var incomingArray = {
"1518744389": 10,
"1318744389": 30
};
//sells
var outgoingArray = {
"1518744480": 3,
"1418744389": 5,
"1408744389": 8
};
and I would like the outcome to show only the remainding incomingArray timestamp purchase pairs.
var incomingArrayRemaining = {
"1518744389": 7,
"1318744389": 17
};
Where you see there was one outgoing transaction for 3 apples at a later timestamp, therefore subtracting from 10. And there were 13 outgoing transactions before the buy of 10, but after the purchase of 30, so they only subtract from the 30.
Note, if more than 10 were transferred after 10, it would subtract from both 10 and 30. The number of apples can never be less than 0.
First, to accomplish my goals it seems that I need to know how many are actually still owned from the lot they were purchased in.
Instead of doing stack subtracting in the LIFO method, it seems like this has to be more like Tax Lot Accounting. Where the lots themselves have to be treated independently.
Therefore I would have to take the timestamp of the first index of the sell in the outgoing array and find the nearest older timestamp of the buy in the incoming array
Here is what I tried:
for (var ink in incomingArray) {
var inInt = parseInt(ink);
for (var outk in outgoingArray) {
if (inInt >= 0) {
var outInt = parseInt(outk);
if (outInt >= inInt) {
inInt = inInt - outInt;
if (intInt < 0) {
outInt = inInt * -1; //remainder
inInt = 0;
} //end if
} //end if
} //end if
} //end innter for
} //end outer for
It is incomplete and the nested for loop solution will already have poor computational time.
That function merely tries to sort the transactions so that only the remaining balance remains, by subtracting an outgoing from the nearest incoming balance, and carrying that remainder to the next incoming balance
I feel like a recursive solution would be better, or maybe something more elegant that I hadn't thought of (nested Object forEach accessor in javascript)
After I get them sorted then I need to actually do the weighted average method, which I have some ideas for already.
First sorting, then weighted average of the remaining quantities.
Anyway, I know the javascript community on StackOverflow is particularly harsh about asking for help but I'm at an impasse because not only do I want a solution, but a computationally efficient solution, so I will probably throw a bounty on it.
You could convert the objects into an array of timestamp-value pairs. Outgoing ones could be negative. Then you can easily sort them after the timestamp and accumulate how you like it:
const purchases = Object.entries(incomingArray).concat(Object.entries(outgoingArray).map(([ts, val]) => ([ts, -val])));
purchases.sort(([ts1, ts2]) => ts1 - ts2);
Now you could iterate over the timespan and store the delta in a new array when the value increases (a new ingoing):
const result = [];
let delta = 0, lastIngoing = purchases[0][0];
for(const [time, value] of purchases){
if(value > 0){
// Store the old
result.push([lastIngoing, delta]);
// Set up new
delta = 0;
lastIngoing = time;
} else {
delta += value;
}
}

Check for prime in a list using sieve of Eratosthenes

I have an array as an input and i want to print the prime numbers that exist in that list. I was able to do that using trial division method. But I am struck at a point while trying to do the same thing using sieve of Eratosthenes method.
I tried it with below code, but got confused on how to compare the end result array with my input array list and return only those values that matches the input list. ( Detailed answer would be helpful as am a beginner in javascript).
var arr=[4,7,10,12,13,19,22,37];
function checkPrime(arr)
{
var output=[],primes=[];
var x=arr.length;
for(i=2;i<=arr[x-1];i++)
primes[i]=1;
for(i=2;i<=arr[x-1];i++)
for(j=2;j<=Math.sqrt(arr[x-1]);j++)
primes[i*j]=0;
for(i=0;i<=arr[x-1];i++){
if(primes[i]==1){
output.push(i);
}
}
return output;
}
console.log(checkPrime(arr));
When creating your output list, you want to compare against the values in arr, not the indices, so you need to replace primes[i] with primes[arr[i]].
So this:
if (primes[i] == 1) {
output.push(i);
}
Becomes this:
if (primes[arr[i]] == 1) {
output.push(arr[i]);
}

How do I format "if val 1 or 4 or 6 or 10"

I have some jquery that checks for the value of a form select and then does something. It works as expected, as follows:
$("#field_1_select_value").bind('change', function (e) {
if($("#field_1_select_value").val() == 1){
// Do stuff
} else {
// Do something else
}
});
I would like to check if the select has other values because the behavior would be the same if you choose a number of different options in the select, and they are not necessarily in series so I can't say greater than or less than X. I want to specify if you choose, for example, 1, 4, 10, or 20... something happens. I tried just using commas based on another answer I found elsewhere like follows:
if($("#field_1_select_value").val() == 1, 4, 10, 20){
But that didn't seem to work. The , acts as a multiselector as I understand it and in documentation it makes sense but I didn't find much on how it can work in an if statement scenario like this. I've seen a lot of similar questions but nothing really pointing out usage on an if statement with val.
Thanks for your input and suggestions.
arrays have an indexOf property you can use. Just be sure to convert the value from field_1_select_value to a number, instead of the string you'll otherwise get back.
The fastest way to do this is with the unary + operator.
if([1, 4, 10, 20].indexOf(+$("#field_1_select_value").val()) >= 0){
A switch case may suit your needs:
switch (parseInt($("#field_1_select_value").val(), 10)) {
case 1:
case 4:
case 10:
case 20:
// do stuff
break;
default:
// do something else
break;
}
You can also use jQuerys inArray:
if($.inArray(+$('#field_1_select_value').val(), [1, 4, 10, 20]) > -1)
Fiddle
maybe you could try something like this:
// this way it's easy to insert new values in case of possible
// changes in the future
var posNums = [1,2,3,4];
var val = $("#field_1_select_value").val()
if(posNumbs.indexOf(val) >= 0){
//some actions
}{
//other actions
}

Categories

Resources