How to reduce a javascript array into half? - javascript

I have an array containing 365 objects (date and value), and I would like to reduce this into half to make plotting faster. The reduction has to occur such that I get every other point in the array. So if the first element is for Jan 1, the second element would be for Jan 3 instead of Jan 2. I can iterate through the array and if the number is odd I can add that to the new array or vice versa. But is there a better/faster way to achieve this? I heard crossfilter.js is made for things like this, but wasn't able to figure out how to use it for this case. Any suggestions?

reduce or filter will work for this.
array.reduce(function(memo, item, index) {
index % 2 && memo.push(item);
return memo;
}, [])
array.filter(function(item, index) { return index % 2; })

What you are looking for is Array.filter. filter can be used to filter out the required values from an array, it will result in an array with length lesser or equal to the original array.
The below code returns all the odd elements in the array:
var array = [1,2,3,4,5,6,7,8,9,10]
array.filter(
function (d,indx) {
return indx%2 != 1
}
)

You can use filter function of array
var numbers = [1, 2, 3, 4, 5];
var odds = numbers.filter(function(index, item) {
return index % 2 == 1;
});

Related

How to get sums of subarrays

While solving online code exercises, I came across this one:
Given a 1-dimensional array of numbers and the number of queries, where each query has start index a, end index b and a number c, find the sum of numbers between indexes a and b (inclusive). For each occurrence of zero within the range [a,b], add the value of c to the sum. For example, numbers = [4,6,0,10], queries = [1,3,20] => for this example we need to get the sum of [4,6,0] (indexes 1-3), and because [4,6,0] has 0, we also need to add 20.
This is my code so far:
function findSum(numbers, queries) {
//declare empty array that will store the numbers
let arr = []
// declare initial sum
let sum = 0;
// get the last element of queries (c)
let lastElement = queries[0].pop()
// loop through queries and push numbers to arr, to sum them in the end
queries[0].slice(0, 2).forEach(x => {
arr.push(numbers[x - 1])
})
// check if arr has 0
let zero = arr.filter(el => el === 0)
// if arr has 0, according to the instructions we need to add the c of the q
if (zero.length != 0) {
sum = arr.reduce((a, b) => a + b, 0) + lastElement
}
else {
sum = arr.reduce((a, b) => a + b, 0)
}
return sum
}
My code works if queries is an array, but in some test cases queries may be array of arrays like [ [ 2, 2, 20 ], [ 1, 2, 10 ] ]. I don't know know how to check the numbers in case if queries is array of arrays. Any suggestions are greatly appreciated.
in some test cases queries may be array of arrays
I would expect that this would always be the case, not just in some cases. This is also clear from your code:
queries[0].pop()
This assumes a 2-dimensional array! The problem is not that you sometimes get a 1-dimensional array and other times a 2-dimensional array. The problem is that although you always get a 2-dimensional array, your code is only looking at the first query -- the one that sits at queries[0].
Instead, you should loop over all queries.
I also assume that the return value of your function must be an array, having an answer for each of the queries. This means that you probably want to have code like this:
function findSum(numbers, queries) {
return queries.map(query => {
// solve the single query
return sum;
});
}
Note that your code is not making the sum correctly, as your arr will have a length of 2 (arr.push(numbers[x - 1]) is executed exactly twice), yet the query could indicate a range with 100 values and you should derive the sum of those 100 values, not just of two.
But even if you fix all that, you'll end up with an inefficient solution that will have to iterate over many values in the input array multiple times. This needs a smarter approach.
Try to think of a way to analyse the input before processing any queries yet. Would there be something useful you could build that would help to quickly get a sum of a subarray without having to iterate that subsection again?
Here are some hints:
Hint #1
Use the following truth:
sum(numbers.slice(start, end)) == sum(numbers.slice(0, end)) - sum(numbers.slice(0, start - 1))
Hint #2
What if you would know the sum from the start of the array to any given index? Like a running sum... So for numbers=[4, 8, 0, 3] you would know [4, 12, 12, 15]. Would that help in calculating a sum for a certain range of [start, end]?
Hint #3
How could you apply the same principle for the special treatment of zeroes?

.filter in double arrays

Helo. I am beginner in this JavaScript journey, and i just hit a wall. I am learning .filter() function on Array. My exercise is:
Return only the rows in the matrix that have all positive integers
I have no problems with single arrays. For example my code with single array:
function positiveRowsOnly (array) {
var result = array.filter(function (ind) {
return ind < 0;
});
return result;
};
console.log(positiveRowsOnly([1, 10, -100, 2, -20, 200, 3, 30, 300]));
its quite simple for me to understand that "ind" in .filter will accept every index from given array and check if ind < 0.
What i am struggling is if i have double arrays. Original exercise is with double arrays.
function positiveRowsOnly (array) {
var result = array.filter(function (ind) {
return ind < 0;
});
return result;
};
console.log(positiveRowsOnly([[1, 10, -100 ], [ 2, -20, 200 ], [ 3, 30, 300 ]]));
On internet i just can not find any deeper meaning how .filter() works: does filter go in one array and gets each index? Does "ind" gets just the first array and not first array index? I was looking at Math functions or indexOf but no luck. I hope you understand my struggle. Can anyone explain how this can be done or most important, how does .filter work in double arrays?
In pseudo code i know, look in array index, if it has a negative number than ignore, else return that array.
The function filter will work the same way regardless of the type of every element within an array. Basically, will loop and test a condition to filter that array.
So, you can use the function every to loop (nested arrays) and check the values from them.
+----- This is the nested array
|
| +----- This is the function 'every' that will loop
| | and check every element.
v v
ind.every(function(n) { -+
return n >= 0 |----> This is the predicate.
}); ^ -+
|
|
+----- This is the test to check every
element within the nested array.
The function every returns true when every element within an array meets a specific predicate (handler, callback, Etc,.), in your case n >= 0.
function positiveRowsOnly(array) {
var result = array.filter(function(ind) {
return ind.every(function(n) {
return n >= 0
});
});
return result;
};
console.log(positiveRowsOnly([
[1, 10, -100],
[2, -20, 200],
[3, 30, 300]
]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
On internet i just can not find any deeper meaning how .filter() works: does filter go in one array and gets each index? Does "ind" gets just the first array and not first array index?
The Array.prototype.filter function will loop over the elements of an array, and pass each element to the callback function you provide (sometimes referred to as a 'predicate'). The index is actually the second argument to your predicate function.
In your case, each element of your outermost array is also an array. So your filter predicate will be passed each of the inner arrays, one at a time. If you want to filter the inner arrays, you'll need to "loop inside your loop", and call the filter function again to find the positive numbers.
Since you only want to return entire positive rows, you may want to look at other functions like Array.prototype.every, which will return a boolean if the predicate function matches. Then you could return the whole, unfiltered row.
A good trick is to try putting a console.log(ind) inside your filter functions so you can see what each element of that array looks like.

Get the highest but also unique number from an array

I have a question. I'm looking for a way to get the higest unique number of an array.
var temp = [1, 8, 8, 8, 4, 2, 7, 7];
Now I want to get the output 4 since that is the unique highest number.
Is there a good & hopefully short way to do that?
Yes, there is:
Math.max(...temp.filter(el => temp.indexOf(el) == temp.lastIndexOf(el)))
Explanation:
First, get the elements which are unique in the array using Array#filter
temp.filter(el => temp.indexOf(el) === temp.lastIndexOf(el)) // [1, 4, 2]
Now, get the max of the numbers from the array using ES6 spread operator
Math.max(...array) // 4
This code is equivalent to
Math.max.apply(Math, array);
If you don't want to get fancy, you can use a sort and loop to check the minimal number of items:
var max = 0;
var reject = 0;
// sort the array in ascending order
temp.sort(function(a,b){return a-b});
for (var i = temp.length - 1; i > 0; i--) {
// find the largest one without a duplicate by iterating backwards
if (temp[i-1] == temp[i] || temp[i] == reject){
reject = temp[i];
console.log(reject+" ");
}
else {
max = temp[i];
break;
}
}
Using the spread operator you can find the hightest number easily
Math.max(...numArray);
The only thing left then is to either filter duplicates from the array beforehand, or remove all the elements that match your maximum number if its a duplicate.
remove beforeHand would be easiest in es6 like this.
Math.max(...numArray.filter(function(value){ return numArray.indexOf(value) === numArray.lastIndexOf(numArray);}));
For a non es6 compatible way to remove duplicates have a look at Remove Duplicates from JavaScript Array, the second answer contains an extensive examinations of several alternatives

Duplicate an array an arbitrary number of times (javascript)

Let's say I'm given an array. The length of this array is 3, and has 3 elements:
var array = ['1','2','3'];
Eventually I will need to check if this array is equal to an array with the same elements, but just twice now. My new array is:
var newArray = ['1','2','3','1','2','3'];
I know I can use array.splice() to duplicate an array, but how can I duplicate it an unknown amount of times? Basically what I want is something that would have the effect of
var dupeArray = array*2;
const duplicateArr = (arr, times) =>
Array(times)
.fill([...arr])
.reduce((a, b) => a.concat(b));
This should work. It creates a new array with a size of how many times you want to duplicate it. It fills it with copies of the array. Then it uses reduce to join all the arrays into a single array.
The simplest solution is often the best one:
function replicate(arr, times) {
var al = arr.length,
rl = al*times,
res = new Array(rl);
for (var i=0; i<rl; i++)
res[i] = arr[i % al];
return res;
}
(or use nested loops such as #UsamaNorman).
However, if you want to be clever, you also can repeatedly concat the array to itself:
function replicate(arr, times) {
for (var parts = []; times > 0; times >>= 1) {
if (times & 1)
parts.push(arr);
arr = arr.concat(arr);
}
return Array.prototype.concat.apply([], parts);
}
Basic but worked for me.
var num = 2;
while(num>0){
array = array.concat(array);
num--}
Here's a fairly concise, non-recursive way of replicating an array an arbitrary number of times:
function replicateArray(array, n) {
// Create an array of size "n" with undefined values
var arrays = Array.apply(null, new Array(n));
// Replace each "undefined" with our array, resulting in an array of n copies of our array
arrays = arrays.map(function() { return array });
// Flatten our array of arrays
return [].concat.apply([], arrays);
}
console.log(replicateArray([1,2,3],4)); // output: [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
What's going on?
The first two lines use apply and map to create an array of "n" copies of your array.
The last line uses apply to flatten our recently generated array of arrays.
Seriously though, what's going on?
If you haven't used apply or map, the code might be confusing.
The first piece of magic sauce here is the use of apply() which makes it possible to either pass an array to a function as though it were a parameter list.
Apply uses three pieces of information: x.apply(y,z)
x is the function being called
y is the object that the function is being called on (if null, it uses global)
z is the parameter list
Put in terms of code, it translates to: y.x(z[0], z[1], z[2],...)
For example
var arrays = Array.apply(null, new Array(n));
is the same as writing
var arrays = Array(undefined,undefined,undefined,... /*Repeat N Times*/);
The second piece of magic is the use of map() which calls a function for each element of an array and creates a list of return values.
This uses two pieces of information: x.map(y)
x is an array
y is a function to be invoked on each element of the array
For example
var returnArray = [1,2,3].map(function(x) {return x + 1;});
would create the array [2,3,4]
In our case we passed in a function which always returns a static value (the array we want to duplicate) which means the result of this map is a list of n copies of our array.
You can do:
var array = ['1','2','3'];
function nplicate(times, array){
//Times = 2, then concat 1 time to duplicate. Times = 3, then concat 2 times for duplicate. Etc.
times = times -1;
var result = array;
while(times > 0){
result = result.concat(array);
times--;
}
return result;
}
console.log(nplicate(2,array));
You concat the same array n times.
Use concat function and some logic: http://www.w3schools.com/jsref/jsref_concat_array.asp
Keep it short and sweet
function repeat(a, n, r) {
return !n ? r : repeat(a, --n, (r||[]).concat(a));
}
console.log(repeat([1,2,3], 4)); // [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
http://jsfiddle.net/fLo3uubk/
if you are inside a loop you can verify the current loop index with the array length and then multiply it's content.
let arr = [1, 2, 3];
if(currentIndex > arr.length){
//if your using a loop, make sure to keep arr at a level that it won't reset each loop
arr.push(...arr);
}
Full Example:
https://jsfiddle.net/5k28yq0L/
I think you will have to write your own function, try this:
function dupArray(var n,var arr){
var newArr=[];
for(var j=0;j<n;j++)
for(var i=0;i<arr.length;i++){
newArr.push(arr[i]);
}
return newArr;
}
A rather crude solution for checking that it duplicates...
You could check for a variation of the length using modulus:
Then if it might be, loop over the contents and compare each value until done. If at any point it doesn't match before ending, then it either didn't repeat or stopped repeating before the end.
if (array2.length % array1.length == 0){
// It might be a dupe
for (var i in array2){
if (i != array1[array2.length % indexOf(i)]) { // Not Repeating }
}
}

How do I get the second largest element from an array in javascript

I have an integer array like this :
arr[20,120,111,215,54,78];
I need a function taking an array as its argument and returning the second largest element of that array.
The most straightforward implementation, without modifying the original array, is to iterate and track the biggest and next biggest:
function nextBiggest(arr) {
let max = -Infinity, result = -Infinity;
for (const value of arr) {
const nr = Number(value)
if (nr > max) {
[result, max] = [max, nr] // save previous max
} else if (nr < max && nr > result) {
result = nr; // new second biggest
}
}
return result;
}
const arr = ['20','120','111','215','54','78'];
console.log(nextBiggest(arr));
Variations
The behaviour of returning -Infinity if there's no next maximum value distinct from the maximum value in a non-empty array can be modified at the end of the function, depending on the requirements.
Same as maximum
return result == -Infinity ? max : result;
For an empty array, this will return -Infinity as before, but would otherwise return the same value as the maximum if no next distinct maximum is found.
Return null
return result == -Infinity ? null : result;
Same as above, but the return value of null is more indicative of the nonexistence of a next distinct maximum.
Original answer
var secondMax = function (){
var arr = [20, 120, 111, 215, 54, 78]; // use int arrays
var max = Math.max.apply(null, arr); // get the max of the array
arr.splice(arr.indexOf(max), 1); // remove max from the array
return Math.max.apply(null, arr); // get the 2nd max
};
demo
Update 1
As pointed out by davin the performance could be enhanced by not doing a splice but temporarily replacing the max value with -Infininty:
var secondMax = function (arr){
var max = Math.max.apply(null, arr), // get the max of the array
maxi = arr.indexOf(max);
arr[maxi] = -Infinity; // replace max in the array with -infinity
var secondMax = Math.max.apply(null, arr); // get the new max
arr[maxi] = max;
return secondMax;
};
Anyway, IMHO the best algorithm is Jack's. 1 pass, with conversion to number.
Mine is just short, using builtin methods and only wanted to provide it as an alternative, to show off all the different ways you can achieve the goal.
Update 2
Edge case with multiple values.
As comments pointed it out: this solution "does not work" if we have an array like [3, 3, 5, 5, 5, 4, 4].
On the other hand it would be also a matter of interpretation what we would consider "the 2nd largest element".
In the example we have:
3 elements with the largest value (5) at indices: 2,3,4
2 elements with the second largest value (4) at indices: 5,6
2 elements with the second smallest value (3) at indices: 1,2
The 2nd largest element could be interpreted as:
the 2nd (largest element) - 5 at index 3 - assuming that there is an order, and that we aim for a unique value
the (2nd largest) element - 4 at index 5 - assuming that there is an order, and that we aim for a unique value
The simplest solution is to sort :
// here's your array :
var stringArray = new Array('20','120','111','215','54','78');
// let's convert it to a real array of numbers, not of strings :
var intArray = stringArray.map(Number);
// now let's sort it and take the second element :
var second = intArray.sort(function(a,b){return b-a})[1];
If you don't want the simplest but the fastest (you probably don't need it), then you'd have to write your for loop and store the two greatest elements while looping.
First sort it backwards and then get the second element:
['20','120','111','215','54','78'].sort(function(a, b) { return b - a; })[1];
// '120'
Obviously works with strings too.
Sort the array and then return the second index.
var arr = ['20','120','111','215','54','78'];
arr.sort(function(a,b){
return b-a;
});
console.log(arr[1]);
You can try this:
function second_highest(arr)
{
var second_highest = arr.sort(function(a, b) { return b - a; })[1];
return second_highest;
}
Sort your array from smallest to largest, then grab second one from the end with .length-2
var myArray =['20','120','111','215','54','78'];
var secondLargest = myArray.sort(function(a,b){return a - b})[myArray.length-2];
alert(secondLargest); //120;
function getSecondLargest(nums) {
return [...new Set(nums)].sort((a,b)=>b-a)[1]
}

Categories

Resources