JQuery retriving the next greatest element - javascript

in JQuery i m having an array like
(1,2,6,8)
I have already selected the first element that is 1 which i have saved in a JQuery variable
submitterid = 1
On clicking a link I am trying to get the next greatest element in the Array than what I have selected in the submitterid..
How can I achieve this?
Edit:
How to find the last element in this array in the code
var previousId;
$("#previous").click(function (){
index = submitters.indexOf(submitterid),
nextId;
if (index - 1 < submitters.length) {
previousId = submitters[index-1];
} else {
// no ID index
// if i am having an array of 1,2,6,8 after moving to 1 from 8 to 6 - 2-1 i am trying to move to the last element of the array
}
alert(previousId);
});// previousId

Why couldn't you do something like:
var arr = [3, 5, 8, 3].sort(function (a, b) { return a - b; } );
var val = arr.pop();
Any keep popping the array -- saying that the values don't need to stay in the array.
If you are randomly picking values and you need the next highest, then write the appropriate sorting function.

You want a counter:
function counter(arr) {
this.arr = arr;
this.index = 0;
}
counter.prototype.next = function() {
return this.arr[this.index++];
}
You instantiate it and use it like:
var nums = new counter([1,2,3,4,5]);
nums.next() ; => 1
nums.next() ; => 2
nums.next() ; => 3

Actually, there is no need to use any jquery-specific stuff for this, apart from the click event handling, just 'plain javascript' will do;
var myArray = [ 1, 2, 6, 8 ];
var submitterid = 1;
$(function() {
$('a#id').click(function(event) {
event.preventDefault();
var greater = -1;
// loop through array
for (var i in myArray)
// find numbers greater than the specified number
if (i > submitterid)
// find numbers closest to specified number
if (i < greater || greater < 0)
greater = i;
if (greater < 0) {
// no greater value found, do something
} else {
// next biggest value is in variable greater, do something with it
}
});
});

You have to loop through the array.
Try this untested code:
// Your test array.
var arrValues = [ "1", "2", "6", "8" ];
var low = 1;
var high = 2;
// Loop over each value in the array.
$.each( arrValues, function( intIndex, objValue ){
if (objValue > high)
hight = objValue;
if (objValue < high)
if (objValue > low)
low = objValue
});
return low;

If your array is already sorted (see sort method), try this:
var arr = [1,2,6,8],
submitterid = 1,
index = arr.indexOf(submitterid),
nextId;
if (index + 1 < arr.length) {
nextId = arr[index+1];
} else {
// no ID index
}

Related

How do I find two numbers in an array that are equal to a target number

I'm looking to find two numbers in an array that are equal to a particular target number. I thought this would be a simple task using .filter but for some reason my code only works when I'm looking for a target number of 4 but doesn't work for anything else?
What am I missing here?
var numbers2 = [1,2,3,4];
var target = 3;
var found = numbers2.filter((num) => {
return (num + num) !== target;
});
console returns (4) [1,2,3,4] as opposed to 2[1,2].
var numbers = [1,4,3,2,6,8,12,1,1,1,2,3,4];
var target = 3;
var output = [];
// Use a set to remove duplicate numbers
numbers = [...new Set(numbers)]; // Only do this step if you dont want duplicates ( like 2+2 = 4 so if your target was for 2, would not show up in the list )
// Sort the numbers from lowest to highest
numbers.sort( (a,b) =>a-b);
// Get index of first number that matches the target or is greater than the target
let index;
for( let i =0; i < numbers.length; i++) {
if( numbers[i] >= target ) {
index = i;
break;
}
}
// Remove all numbers from the array starting at the previous index as these are not possible to add up with another number to the target
if( index ) {
numbers.splice(index, numbers.length - index );
}
// Loop through the remianing array to get first number
numbers.forEach( ( num1, index1) => {
// Loop through array again to get second number
numbers.forEach( (num2, index2) => {
// Check if number is same is same index as you dont want to add the same value to itself, then check if the 2 numbers equal the target number
if( index1 !== index2 && num1 + num2 === target ) {
// If number already exists in array dont duplicate otherwise add it to the array
if( output.indexOf( num1 ) == -1 ) {
output.push( num1);
}
// If number already exists in array dont duplicate otherwise add it to the array
if( output.indexOf( num2 ) == -1 ) {
output.push( num2);
}
}
});
});
console.log( output);
You could find the array location of your target number through using a array.forEach, array.indexOf(), array.find(), and array.findIndex():
let numbers2 = [1,2,3,4];
let target = 4;
//Using foreach
numbers2.forEach((item, index)=>{
if (item == target){
console.log("Found the target at array location "+index);
}
});
//Or through using indexOf():
console.log("Found the target at array location "+numbers2.indexOf(target));
//Or through using find():
const found = numbers2.find(element => element == target);
console.log("Found "+target+" in the array.");
//Or through findIndex():
const target1 = (a) => a == target;
console.log("Found the target at array location "+numbers2.findIndex(target1));
Assuming:
you only need one pair
[2,2] does not count when your target is 4 (as '2' only appears once in the array)
One way to go is:
let numbers = [1, 2, 3, 4]
let target = 4;
let output = [];
const N = numbers.length
outer: for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
if (numbers[i] + numbers[j] === target) {
output.push(numbers[i], numbers[j])
break outer;
}
}
}
console.log(output); //[1,3]
Edit: even if you want more than one pair, it's easy to modify to get that effect (now the target is 5):
let numbers = [1, 2, 3, 4]
let target = 5;
let output = [];
const N = numbers.length
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
if (numbers[i] + numbers[j] === target) {
output.push([numbers[i], numbers[j]])
}
}
}
console.log(output); //[[1,4], [2,3]]
This is an ideal case for the humble for loop. Methods like .forEach() will always try to loop over all the elements in an array, but if we order the data before we start the search we can break early and eliminate a lot of searching.
Ergo...
var numbers = [1,2,3,4];
var target = 5;
var output = [];
// Handling ordered data is much faster than random data so we'll do this first
numbers.sort();
// We want to start the inner search part way up the array, and we also want
// the option to break so use conventional for loops.
for (let i = 0; i<numbers.length; i++) {
for (let j=i+1; j<numbers.length;j++) {
// If the total = target, store the numbers and break the inner loop since later numbers
// will all be too large
if ((numbers[i]+numbers[j])===target) {
output.push([numbers[i], numbers[j]]);
break;
}
}
// Stop searching the first loop once we reach halfway, since any subsequent result
// will already have been found.
if (numbers[i]>(target/2)) {
break;
}
}
console.log( output);
It makes very little sense to get an array of single numbers, because you'll get all the numbers except for the last one unless the array starts at zero or there are numbers skipped. So I've written a function that'll return an array of single numbers or an array of expressions (strings).
First, make a copy of the array:
const array = [1, 2, 3, 4]
const copy = array.slice(0);
Next, use .flatMap() for the first set of iterations:
array.flatMap(num => { // This is the outer loop of numbers
If the third parameter expression is undefined it will default to false. Then .filter() the copy array, the criteria being that the number from the outer loop plus the current number of the inner loop equals the target number AND the numbers cannot be identical.
copy.filter(n => n !== num && target === n + num);
/*
Iterations on the first iteration of outer loop
1 + 1, 1 + 2, 1 + 3,...
*/
If expression is true, then use .flatMap() to return an expression (string) of whatever equals the target number or an empty array (which returns as nothing since .flatMap() flattens it's returns by a level). If both numbers are identical an empty array will be returned.
copy.flatMap(n => n === num ? [] :
target === n + num ? `${n} + ${num}` :
[]
);
If expression is true half of the array is returned so that there isn't any reversed dupes (ex. 6+2 and 2+6)
let half = result.length / 2;
result = result.slice(0, half);
const log = data => console.log(JSON.stringify(data));
// [1, 2, 3,...10]
const array10 = [...new Array(10)].map((_, i) => i + 1);
// [0, 2, 4, 6,...18]
const arrayEven = [...new Array(10)].map((_, i) => i * 2);
function operands(array, target, expression = false) {
const copy = array.slice(0);
let result = array.flatMap(num => {
if (expression) {
return copy.flatMap((n, i) =>
num === n ? [] :
target === n + num ? `${n} + ${num}` :
[]
);
}
return copy.filter(n => n !== num && target === n + num);
});
if (expression) {
let half = result.length / 2;
result = result.slice(0, half);
}
return result;
}
// Return as an array of single numbers
log(array10);
log('3: '+operands(array10, 3));
log('8: '+operands(array10, 8));
log('5: '+operands(array10, 5));
log(arrayEven);
log('2: '+operands(arrayEven, 2));
log('8: '+operands(arrayEven, 8));
log('15: '+operands(arrayEven, 15));
log('=======================');
// Return as an array of expressions (string)
log(array10);
log('3: '+operands(array10, 3, true));
log('8: '+operands(array10, 8, true));
log('5: '+operands(array10, 5, true));
log(arrayEven);
log('2: '+operands(arrayEven, 2, true));
log('8: '+operands(arrayEven, 8, true));
log('15: '+operands(arrayEven, 15, true));

Javascript variable assignment in nested for loop

I am pulling my hair out with this algorithm. The goal is to take number array as an input and output a string that has all sequential numbers displayed as a range. For example if my input were [1,2,4,6,7,8,] my output should be "1-2,4,6-8". My issue lies with the variable assignment in my nested for loop's if statement. IndexEn is overridden each time j increments and should ultimately exit the inside loop as the highest value. The problem is that when I try to call the variable outside of the for loop it passes each value of IndexEn instead of the maximum. I don't understand how IndexEn is able to be outside of the scope of the inner loop while the inner loop is still running? Can someone please help me fix and understand whats happening here?
function bkInd(arr){
var bookSt="";
var indexSt;
var indexEn;
for(var i =0;i<arr.length-1;i++){
if(arr[i+1] !== (arr[i]+1)) {
if(i===0 || (i>0 && arr[i]) !== (arr[i-1]+1) ){
bookSt+= arr[i]+",";
}
// check to see if number are sequential and SHOULD output starting index value - last value
}else{
for(var j=i+1;j<arr.length;j++){
var count=0;
if(arr[j]==(arr[i +count]+1)){
indexSt = arr[i];
indexEn = arr[j];
count+=1;
}
}
//concatenate string
//console.log(indexEn); for value of index
bookSt+= indexSt+"-"+indexEn+",";
}
}
return bookSt;
}
var bookList = [1,3,4,5,7,9,10,11];
document.write(bkInd(bookList));
I don't like nested looping (can be slow on large datasets) so I took a different approach, hope you don't mind:
var bkInd = function(arr) {
var result = [];
var seq = []; // 'Temporary' array
for(var i = 0; i < arr.length; i++) {
seq.push(arr[i])
if(arr[i] + 1 !== arr[i + 1]) {
result.push(seq.length > 1 ? seq[0] + '-' + seq.pop() : arr[i]);
seq = [];
}
}
return result.join(', ')
}
// => '1, 3-5, 7, 9-11'
It instead 'builds up' a temporary array of numbers (seq) as it loops through arr. If the next number is sequential, seq keeps the last number and the loop continues. If the next number is more than one above the current one, seq is pushed to result, but if seq is more than one index long it will concatenate these to a hyphenated string. After seq get pushed, it gets reset to an empty array. Finally, it joins the result array with commas.
Code is updated according to your requirement :
function bkInd(arr){
var bookSt="";
var indexSt;
var indexEn;
for(var i =0;i<arr.length-1;i++){
if(arr[i+1] !== (arr[i]+1)) {
if(i===0 || (i>0 && arr[i]) !== (arr[i-1]+1) ){
bookSt+= arr[i]+",";
}
// check to see if number are sequential and SHOULD output starting index value - last value
}else{
var count=1;
indexSt = arr[i];
for(var j=i;j<arr.length;j++){
if(arr[j]==(indexSt+count)){
indexEn = arr[j];
count+=1;
i++;
}
}
//concatenate string
//console.log(indexEn); for value of index
bookSt+= indexSt+"-"+indexEn+",";
}
}
return bookSt;
}
var bookList = [1,3,4,5,7,9,10,11];
console.log(bkInd(bookList));
Your inner for loop logic was incorrect. I have updated the code to meet the requirement.
Scope is the region of the code within which a variable is directly accessible.
In JS scope is defined by functions, blocks (i.e. { and }) for let, const and by catch blocks.
The following seems to work:
function runnify(arr) {
var runFrom;
return arr.reduce((p,c,i)=>{
if (c + 1 === arr[++i]) { // true if next item is sequential
if (runFrom == null ) { // We are at start of run
runFrom = c;
}
return p;
}
if (runFrom) { // We are at the end of a run
p.push(`${runFrom}-${c}`);
runFrom = null;
return p;
}
p.push(c); // Not sequential
return p;
}, []).join(',');
}
var seq = [1, 3, 4, 5, 7, 9, 10, 11];
document.write(runnify(seq));
Basically, you could collect all items with a check, if consecutive in an array and join it at the end, for consecutive elements with a dash and the rest with comma.
function consecutive(array) {
return array.reduce(function (r, a,i) {
var last = r[r.length - 1];
if (!i || last[last.length - 1] + 1 !== a) {
r.push([a]);
} else {
last[1] = a;
}
return r;
}, []).map(function (a) { return a.join('-'); }).join();
}
var array = [1, 3, 4, 5, 7, 9, 10, 11],
grouped = consecutive(array);
console.log(grouped);

Find biggest subarray in a 2d array in JavaScript

Given an array I want to find the largest sub array by the length i.e
var table = [
["Protein",["Grilled Chicken","Lamb"]],
["Fats",["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables",["Carrots","Eggs","Milks","Peppers"]]
];
I want it to return ["Carrots","Eggs","Milks","Peppers"]
Heres my code
function findBiggestSubArray(array){
var biggestArrayIndex = 0;
for(var i=0;i<array.length;i++){
if(i === (array.length-1)){
//We have reached the end of the array then return the array
console.log("Reached the End");
return array[biggestArrayIndex];
} else {
if(!array[biggestArrayIndex][1].length >= array[i][1].length){
biggestArrayIndex = i;
}//End of Inner else block
}//End of Outer else block
}//End of forloop
}
General solution, to find the most largest array in an array-structure:
I would do it with recursion, so the most biggest Array will be found, in any depth..
/**
* array -> The array to check,
* biggestArray -> The most biggestArray found so far
*/
function findBiggestArray(array, biggestArray){
biggestArray = biggestArray || [];
if (array.length > biggestArray.length)
biggestArray = array;
for (var i = 0; i < array.length; i++) {
if (array[i] instanceof Array)
biggestArray = findBiggestArray(array[i],biggestArray)
}
return biggestArray;
}
var multiArray = [
["1", "2", ["234", "334"]],
[1,2,3,4,5, [1,2,3,4,5,6,7,7]]
]
var biggest = findBiggestArray(multiArray)
console.log(biggest)
// This also works!
console.log(findBiggestArray([1, [1,2,3]]))
Oneliner for this special case
// Sort the array by the length of the subarray at position 1, and return the first item
var category = table.sort(function(a, b) { return b[1].length - a[1].length })[0]
// ES6-Syntax
var category = table.sort((a, b) => b[1].length - a[1].length)[0]
category // => ["CategoryName", [ITEMS..]]
I would do this way (see the comments in the code for explanation):
var table = [
["Protein", ["Grilled Chicken", "Lamb"]],
["Fats", ["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables", ["Carrots", "Eggs", "Milks", "Peppers"]]
];
function findBiggestSubArray (array) {
// Initialise empty array.
var bigSubArray = ["", []];
// Loop through the given array.
for (var i = 0; i < array.length; i++) {
// Check if the current biggest one is bigger than the saved array.
if (array[i][1].length > bigSubArray[1].length) {
// If bigger, replace it with current array.
bigSubArray = array[i];
}
}
// Return the biggest sub array.
return bigSubArray[1];
}
console.log(findBiggestSubArray(table));

Javascript: take every nth Element of Array

I get an Array with an unknown Number of data.
But I only have an predefined amount of data to be shown/store.
How can I take every nth Element of the initial Array and reduce it in JavaScript?
Eg.: I get an Array with size=10000, but are only able to show n=2k Elements.
I tried it like that:
delta= Math.round(10*n/size)/10 = 0.2 -> take every 5th Element of the initial Array.
for (i = 0; i < oldArr.length; i++) {
arr[i] = oldArr[i].filter(function (value, index, ar) {
if (index % delta != 0) return false;
return true;
});
}
With 0.2 it´s always 0, but with some other deltas (0.3) it is working. Same for delta=0.4, i works, but every second Element is taken with that. What can I do to get this to work?
Maybe one solution :
avoid filter because you don't want to loop over 10 000 elements !
just access them directly with a for loop !
var log = function(val){document.body.innerHTML+='<div></pre>'+val+'</pre></div>'}
var oldArr = [0,1,2,3,4,5,6,7,8,9,10]
var arr = [];
var maxVal = 5;
var delta = Math.floor( oldArr.length / maxVal );
// avoid filter because you don't want
// to loop over 10000 elements !
// just access them directly with a for loop !
// |
// V
for (i = 0; i < oldArr.length; i=i+delta) {
arr.push(oldArr[i]);
}
log('delta : ' + delta + ' length = ' + oldArr.length) ;
log(arr);
Filter itself returns an array. If I'm understanding you correctly, you don't need that surrounding loop. So:
newArr = oldArr.filter(function(value, index, Arr) {
return index % 3 == 0;
});
will set newArr to every third value in oldArr.
Try
arr = oldArr.filter(function (value, index, ar) {
return (index % ratio == 0);
} );
where ratio is 2 if you want arr to be 1/2 of oldArr, 3 if you want it to be 1/3 of oldArr and so on.
ratio = Math.ceil(oldArr.length / size); // size in the new `arr` size
You were calling filter() on each element of oldAdd inside a loop and you're supposed to call filter() on the whole array to get a new filtered array back.
Borrowing from #anonomyous0day's solution, generate a new Array with the desired indices from the given array:
(Take every 3 items)
Array.prototype.take = function(n) {
if (!Number(n) && n !== 0) {
throw new TypeError(`Array.take requires passing in a number. Passed in ${typeof n}`);
} else if (n <= 0) {
throw new RangeError(`Array.take requires a number greater than 0. Passed in ${n}`);
}
const selectedIndicesLength = Math.floor(this.length / n);
return [...Array(selectedIndicesLength)].map((item, index) => this[index * n + 1]);
};
[1, 2, 3, 4, 5, 6, 7, 8].take(2); // => 2, 4, 6, 8
this also works by using map to create the new array without iterating over all elements in the old array..
// create array with 10k entries
const oldArr = [ ...Array( 10000 ) ].map( ( _el, i ) => i );
const max = 10;
const delta = Math.floor( oldArr.length / max );
const newArr = [ ...Array( max ) ].map( ( _el, i ) => (
oldArr[ i * delta ]
) );
console.log( newArr );
may help!
const myFunction = (a, n) => {
let array = []
for(i = n; i <= a.length; i += n){
array.push(a[i-1]);
}
return array;
}

Drop last element of javascript array when array reaches specific length

I would like to cache some data in javascript, but the cache should be limited to 10 elements for example.
I can place the objects in javascript array, but what is the best way to keep the array limited to 10 elements?
Example:
function getData(dataId) { return new NextDataObject(dataId); }
var array = new Array();
array.push(getData(0));
array.push(getData(1));
(...)
array.push(getData(10)); // this should result in dropping "oldest" data, so getData(0) should be removed from the array, so that in array there are only 10 objects at maximum
Should such mechanism be written manually (using splice() for example?) or are there better ways to achieve such "cache" structure in javascript?
BTW: in this particular situation I'm using angular.
Override the push function of your caching array.
var array = new Array()
array.push = function (){
if (this.length >= 10) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
Plunker
To make this more reusable I created a method which returns new instance of such array (basing on above code).
function getArrayWithLimitedLength(length) {
var array = new Array();
array.push = function () {
if (this.length >= length) {
this.shift();
}
return Array.prototype.push.apply(this,arguments);
}
return array;
}
var array = getArrayWithLimitedLength(10);
To remove first element from array use shift:
if (arr.length > 10) {
arr.shift(); // removes the first element from an array
}
How about this object?
function Cache(maxLength) {
this.values = [];
this.store = function(data) {
if(this.values.length >= maxLength) {
this.getLast();
}
return this.values.push(data);
}
this.getLast = function() {
return this.values.splice(0,1)[0];
}
}
cache = new Cache(3);
// => Cache {values: Array[0]}
cache.store(1)
// => 1
cache.store(2)
// =>2
cache.store(3)
// => 3
cache.store(4)
// =>3
cache.values
// => [2, 3, 4]
cache.getLast()
// => 2
cache.values
[3, 4]
You could create new method in Array.prototype to mimic your needs.
Array.prototype.push_with_limit = function(element, limit){
var limit = limit || 10;
var length = this.length;
if( length == limit ){
this.shift();
}
this.push(element);
}
var arr = []
arr.push_with_limit(4); // [4]
arr.push_with_limit(9); // [4, 9]
....
// 11th element
arr.push_with_limit(3); // [9, ..., 3] 10 elements
Simple fixed length queue:
Array.prototype.qpush = function( vals, fixed ) {
if (arguments.length) {
if (Array.isArray(vals)) {
for (var v of vals) {
this.push(v);
}
} else {
this.push(vals);
}
var _f = (typeof this.fixed != undefined) ? this.fixed : 0;
if (typeof fixed != undefined) {
_f = (Number(fixed)===fixed && fixed%1===0 ) ? fixed : _f;
}
this.fixed = _f;
if (this.fixed>0) this.splice(0, this.length - _f);
}
}
var q = new Array();
q.push(0);
q.qpush( [1, 2, 3], 10 );
q.qpush( [4] );
q.qpush( 5 );
q.qpush( [6, 7, 8, 9, 10, {k:"object"} ] );
console.log(q);
if(array.length == 10) {
array.splice(0, 1);
// this will delete first element in array
}
If you do a check whether the array has reached 10 entries with array.length, just remove the first element before pushing a new element. This can be done several ways as Tushar states, array.shift() would be the fastest, but you can indeed use array.splice() aswell.
It would look like this:
if(array.length > 10) {
array.shift();
array.push(getData(10));
}
On a side note, instead of using var array = new Array() I suggest you simply use var array = [];. This is because the new keyword in Javascript sometimes has bad side effects. If you for example want to create an array with 1 element being a digit, and you use var arr = new Array(12);, an array with 12 undefined elements will be created. Whereas var arr = [12]; will create an array with 1 element, the digit 12.
But I guess that's a minor thing to consider..
You could use an object instead...
var obj = {}; //your cache object
obj[window.performance.now()] = getData(val); //add value, index by microsecond timestamp
if(Object.keys(obj).length > 10){ // then if the length ever gets bigger than 10..
var array = Object.keys(obj).sort(); //sort the properties by microsecond asc
delete obj[array[0]]; //delete the oldest one
}
Here is a jsFiddle example showing how it works: https://jsfiddle.net/uhkvk4mw/
just check if the length is reached then pop it
if(arr.length > someNumber){
arr.pop(); // pop() will remove the last element
}

Categories