Looping through two different selectors at the same time - javascript

I am using JQuery to calculate some totals figures and I have run into a problem.
Let's say I have two sets of inputs, each with a unique name.
$('[name="quantity\\[\\]"]')
$('[name="price\\[\\]"]')
I want to cycle through each set of inputs at the same time so that I can check both for (!isNaN) and (length !== 0), and if the values are valid, I want to multiply them together and add to a running total.
I know I can cycle through one selector using each(), but how can I cycle through two at the same time? is there an elegant way to accomplish this goal?

All cute things jQuery aside, here is a generic "zip" function.
a and b should be arrays (or at least array-like). If fn is supplied this will act as a map over each pair of items. Remember that jQuery objects are arrays.
function zip (a, b, fn) {
var len = Math.max(a.length, b.length)
var result = []
if (fn) {
for (var i = 0; i < len; i++) {
result.push(fn(a[i], b[i]))
}
} else {
for (var i = 0; i < len; i++) {
result.push([a[i], b[i]])
}
}
return result
}
Example:
var z = zip([1,2,3], ['a','b'])
// z = [[1,'a'],[2,'b'],[3,undefined]
for (var i = 0; i < z.length; i++) {
var elm = z[i]
var a = elm[0]
var b = elm[1]
alert(a + "-" + b)
}
Example with fn:
zip([1,2,3], ['a','b'], function (a, b) {
alert(a + "-" + b)
})
Example in jQuery'ish context:
var total = 0
zip(
$('[name="quantity\\[\\]"]'),
$('[name="price\\[\\]"]'),
function (a, b) {
// if either a or b are undefined, there is already a problem
// the `expr || 0` is to silently handle cases of `NaN || 0` which may
// result if the price or quantity are garbage values
var qty = parseInt($(a).val(), 10) || 0
var price = parseInt($(b).val(), 10) || 0
total += qty * price
})
Happy coding.

Here's a straight forward solution
var quantities = $('[name="quantity\\[\\]"]'),
prices = $('[name="price\\[\\]"]');
var len = Math.max(quantities.size(), prices.size());
for (var i=0; i < len; i++) {
var quantity = quantities.get(i);
var price = prices.get(i);
// Do whatever you want with quantity and price
}

Store the result of the selection in a variable, and use the index argument for the each when enumerating to reference the related element in the other set.
var quan = $('[name="quantity\\[\\]"]');
var price = $('[name="price\\[\\]"]');
var total = 0;
quan.each(function( index ) {
var quan_val = +$(this).val();
var price_val = +price.eq( index ).val();
if( quan_val && price_val ) {
total += (quan_val * price_val);
}
});
alert( total );

How about this:
function getValue() { return this.value; }
var valsA = $('input[name="quantity\\[\\]"]').map(getValue).get(),
valsB = $('input[name="price\\[\\]"]').map(getValue).get();
for ( var i = 0; i < valsA.length; i++ ) {
// work with valsA[i] and valsB[i] here
}

var prices = $('[name="price\\[\\]"]');
$('[name="quantity\\[\\]"]').each(function(i){
var quantity = this;
var price = prices[i];
// Compare them here.
});

Use a comma:
$('[name="quantity\\[\\]"], [name="price\\[\\]"]')

loop and use the index
var quantity = $('[name="quantity\\[\\]"]')
$('[name="price\\[\\]"]').each( function(ind){
var currentPrice = $(this);
var currentQuantity = quantity.eq(ind);
});
or something like
$('[name="price\\[\\]"]').each( function(ind){
var currentPrice = $(this);
var currentQuantity = currentPrice.closest('[name="quantity\\[\\]"]');
});

Related

matching two array data and get sum of it! (algorithm...?)

I want to match time and date
and result should be sum of time for each date...
for example...06/27 - should be sum of 30 and 90...so on.
How can I do that...
var array_date=["2017/06/27","2017/06/26","2017/06/27","2017/06/26","2017/06/28"]
var array_time=["30","50","90","120","20"]
var obj = array_date;
for (var i = 0 in obj) {
console.log("rr:"+obj[i]);
}
//To filter date I used below method...anyway.
var cleanArray = displayed_date.filter((value,index,self)=>{ return (self.indexOf(value) === index )});
First, since you're doing addition, best to convert your strings to numbers:
array_time = array_time.map(t=> +t);
Next, group and sum the times by date:
let data = array_date.reduce((acc, d, i)=> {
if(acc.hasOwnProperty(d)) acc[d] += array_time[i];
else acc[d] = array_time[i];
return acc;
}, {});
jsfiddle
You can do it just like this:
<script>
array_date=["2017/06/27","2017/06/26","2017/06/27","2017/06/26","2017/06/28"];
array_time=["30","50","90","120","20"];
var oData = [];
for(var i = 0; i < array_date.length; i++ ){
if(Object.keys(oData).length > 0){
var icount = 0;
for(var x = 0; x < Object.keys(oData).length; x++){
if(oData[x]['date'] == array_date[i]){
oData[x]['sum'] = parseInt(oData[x]['sum']) + parseInt(array_time[i]);
icount++;
}
}
if(icount == 0){
var oCreate = {"date":array_date[i], "sum":parseInt(array_time[i])}
oData.push(oCreate);
}
}else{
var oCreate = {"date":array_date[i], "sum":parseInt(array_time[i])}
oData.push(oCreate);
}
}
console.log(JSON.stringify(oData)); //oData is the final variable answer here.
</script>
Hope it will help.

JS : Biggest element of an array, less than a given variable

Given :
var array = [1,2,5,10];
var limit = 8;
I am looking for a way to find the biggest element of the array, less than the limit 8. something like :
Math.max(array, "while < limit");
I tried :
Math.min(Math.max(array), limit)
which does not work in all cases for array and limit, obviously.
EDIT :
The input array is not necessarily sorted :
var array = [10,-10,10,-10];
var limit = 5;
Expected result is -10.
var array = [1,2,5,10];
var limit = 8;
alert(Math.max.apply(Math, array.filter(function(x){return x <= limit})));
You can sort, filter and then pop
var array = [1,2,5,10];
var limit = 8;
var largest = array.sort().filter(item => (item < limit)).pop();
console.log(largest);
You can either just do a simple for loop, you can filter all numbers less than the max and sort and max, or you can use reduce which is just like doing a for loop.
for loop (could use forEach)
var array = [1, 2, 5, 10];
var limit = 8;
var result = array[1];
for (var i = 1; i < array.length; i++) {
if (array[i] <= limit && array[i] > result) {
result = array[i];
}
}
console.log(result);
Filter with Max
var array = [1, 2, 5, 10];
var limit = 8;
var result = Math.max.apply([], array.filter(function(val) {
return val < limit
}));
console.log(result);
Reduce
var array = [1,2,5,10];
var limit = 8;
var temp = array[0];
var result = array.reduce( function (num, val ) {
return val > num && val <= limit ? val : num
}, temp);
console.log(result)
You can try in this way:
var array = [1,2,5,10,7];
var limit = 8;
var max=0;
for(var i=0;i<array.length;i++)
{
if(array[i] > max && array[i] < limit)
max=array[i];
}
console.log(max);
var array = [1,2,5,10];
var limit = 8;
var closest = null;
array.forEach(function(el){
if (el <= limit && (closest == null || (limit - el) < (limit - closest))) {
closest = el;
}
});
alert(closest);

Find out if array contains arithmetic progression in javascript

I have an array:
var myarray = [1,2,3,4,7,9,12,13,14]
I need to group values like so:
var array_1 = 1,2,3,4
var array_2 = 7
var array_3 = 8
var array_4 = 12,13,14
I need to find a sequences with an arithmetic progression and seperate from other values.
Any ideas?
Check out this solution
function explode(myarray)
{
var multi = [];
var i = j = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
{
i++;
j=0;
}
if(j==0)
multi[i] = [];
multi[i][j] = myarray[key];
j++;
}
return multi;
}
It returns a multidimentionnal array that you can use in your example like this
var myarray = [1,2,3,4,7,9,12,13,14];
var multi_array = explode(myarray);
var array_1 = multi_array[0];
var array_2 = multi_array[1];
var array_3 = multi_array[2];
var array_4 = multi_array[3];
New update :
You can also remove the j index and use .push to add new elements to your array
function explode(myarray)
{
var multi = [];
var i = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
i++;
if(!multi[i])
multi[i] = [];
multi[i].push(myarray[key]);
}
return multi;
}
The following seems to work, but displays a slightly different output than the one you expect.
In your example, I think 7 and 9 should be grouped (any sequence of two items is an arithmetic
progression after all). Or if they are not grouped, then 12 should not be grouped with 13 and
14 either, since 12-9 != 13-12
function split(arr) {
if (arr.length < 2) {
return;
}
var delta = undefined;
var start = 0;
for (var idx = 1; idx < arr.length; idx++) {
if (delta === undefined) {
delta = arr[idx] - arr[idx - 1];
}
if (arr[idx] - arr[idx - 1] != delta) {
alert("subarray " + arr.slice(start, idx));
start = idx;
delta = undefined;
}
}
alert("subarray from" + arr.slice(start, arr.length));
}
split([1,2,3,4,7,9,12,13,14]);
arrays = Array();
var c = 0;
array[c][] = myarray[0]);
for (var i = 1; i<myarray.length; i++) {
if (myarray[i-1] +1 != myarray[i])
c++;
array[c][] = push(myarray[i]);
}
not sure the array syntax (might mix up languages here) is correct or whether I understand your problem fully.

Find value of 100 latest values in array

I've got an array that is constantly updating with analogue readings from an Arduino pin.
I'd like to create a function that takes the latest 100 values in the array, and returns an average of them (the array has a max length of 100,000 at which it starts 'shifting' and 'pushing' to make space for new values).
I created this function, but it returns 'NaN' every time:
function returnAverage(){
var averageArray = [];
var sum = 0;
var sampleEnd = values.length
for (var x = sampleEnd - 100; x < sampleEnd; x++) {
averageArray[x] = values[x]
}
for(var i = 0; i < averageArray.length; i++){
sum += parseInt(averageArray[i]);
}
var avg = sum/averageArray.length;
console.log(avg)
}
Any ideas?
If values is a array of numbers, last maximum 100 items average:
function returnAverage(values) {
var arr = values.slice(-100);
return arr.reduce(function(a, b){ return a + b; }, 0) / (arr.length || 1);
}
Issue number one is that the final value of sum and averageArray.lnegth is 0.
It seems this would happen because the "value" array is empty.
See example below:
var values = [0,1,2,3,4,5,6];
var averageArray = [];
var sum = 0;
var sampleEnd = values.length
for (var x = sampleEnd - 7; x < sampleEnd; x++) {
averageArray[x] = values[x]
}
for(var i = 0; i < averageArray.length; i++){
sum += parseInt(averageArray[i]);
}
var avg = sum/averageArray.length;
console.log(avg)
Edit: NaN is a result of division by zero. So you might want to check for that before calculating:
if(sum == 0 || averageArray.length == 0)
{
return 0;
}

Using Javascript find array values in another array and in order

Here is one to get your brain going! I've not had any luck with it.
[1,2,1,1,2,1,1,1,2,2]
[1,2,1,1,2,1]
I would like to use the second array to find the values in the first, but they must be in the same order.
Once for I would like it to return the next key up from the last key in the second array.
So in this example it would use the first six digits in the first array and then return 6 as the key after the final one in the second array.
var a2 = [1,2,1,1,2,1,1,1,2,2]
var a1 = [1,2,1,1,0,1]
function find(arr1, arr2) {
var len = 1
var result = 0;
var s2 = arr2.toString();
for (len=1;len <= a1.length; len++)
{
var aa1 = arr1.slice(0, len)
var s1 = aa1.toString();
if(s2.indexOf(s1)>=0){
result = aa1.length;
}
else {
break;
}
}
return result;
}
alert(find(a1, a2));
var find = function(haystack, needle) {
var doesMatch = function(offset) {
for (var i = 0; i < needle.length; i++) {
if (haystack[i+offset] !== needle[i]) {
return false;
}
}
return true;
};
for (var j=0; j < haystack.length - needle.length; j++) {
if (doesMatch(j)) {
return j;
}
}
return -1;
};
This is quick, this is dirty, and this is correct only if your data doesn't include any comma.
var needle = [1,2,1,1,2,1];
var haystack = [1,2,1,1,2,1,1,1,2,2];
if ( needle.length <= 0 ) return 0;
var fromStr = ','+haystack.toString()+','
var findStr = ','+needle.toString()+','
// Find ',1,2,1,1,2,1,' in ',1,2,1,1,2,1,1,1,2,2,'
var pos = fromStr.indexOf(findStr);
// Count the end position requested
return pos >= 0 ? fromStr.slice(0,pos+1).match(/,/g).length + needle.length - 1 : -1;
Note: The comma at head and tail is to make sure [22,12] doesn't match [2,1].

Categories

Resources