write a function finding maximum/minimum of array in javascript - javascript

[WITHOUT USING MIN/MATH Function]
The question ask me to create the function including 2 parameters.first is an array and the second parameter is either the String “Minimum” or “Maximum” . It confusing me when i don't know how to input the parameter as the string in the function. So that i decide to create 2 similar function as extremeValue(vector, maximum) and extremeValue(vector, minimum) ( I still don't know whether i can do that or not ).
And this is my code for extremeValue(vector, maximum).
So the way i did is create the array which have the same value with vector[i] than i using if statement to see if it bigger than that vector or not. However, The code is doesn't work. :(
var vector = [3, 1, 1]
var maximum
//------------this function give us the vector with all same value---------------//
function set(value, len) {
var arr = [];
for (var i = 0; i < len; i++) {
arr.push(value);
}
return arr;
}
//---------------------------------------------------//
//---------------------------------------------------//
function extremeValue(vector, maximum) {
var answer = "";
for (var count = 1; count++; count < vector.length) {
if (set(vector[count], vector.length) > vector)
answer += vector[count] + "is maximum"
}
return answer
}
//---------------------------------------------------//
console.log(extremeValue(vector, maximum))

Without using Math or any other javascript function, you can find the max and min values of an array as below.
var arr = [2, 3, 5, 10, 2, -9, 3];
alert("Max value is " + arrayMaxMin(arr, "Max"));
alert("Min value is " + arrayMaxMin(arr, "Min"));
function arrayMaxMin(array, selector) {
var val = array[0]; // variable to hold the current max/min value.
for (var i = 1; i < array.length; i++) {
if (selector == "Min") {
if (array[i] < val) {
val = array[i];
}
} else if (selector == "Max") {
if (array[i] > val) {
val = array[i];
}
}
}
return val;
}

You can use Math functions. Math.min will return you the smallest number of the passed numbers. You cannot call these functions directly on array so, you can use apply to call these functions and pass the array as parameters to the functions.
The Math.min() function returns the smallest of zero or more numbers.
Math.max as follow:
// array: The source array
// type: 'max' or 'min' to find Maximum or Minimum number
var getNum = function(array, type) {
return Math[type].apply(null, array);
};
var arr = [1, 3, 35, 12];
document.write('Max: ' + getNum(arr, 'max'));
document.write('<br />Min: ' + getNum(arr, 'min'));
UPDATE
they does not allow us use min max function
You can use array methods to get maximum and minimum value. Sort the array in ascending order and then the first element in array will be minimum and last element is maximum.
// array: Source array
// type: 'max' or 'min'
var getNum = function(array, type) {
// Sort the array by ascending order
array.sort(function(a, b) {
return a < b;
});
return type === 'max' ? array[0] : array[array.length - 1];
};
var vector = [233, 10, 32543, 54321];
var max = getNum(vector, 'max');
var min = getNum(vector, 'min');
document.write('Max: ' + max);
document.write('<br />Min: ' + min);

This should work too!. Hope it helps bro.
var arr = [2 ,4 ,56, 23, 10];
var max = arr.reduce(function(x,y){
return (x > y) ? x : y;
});
var min = arr.reduce(function(x,y){
return (x < y) ? x : y;
});
console.log('Max: '+ max);
console.log('Min: '+ min);

You could do something like this:
function extremeValue(my_arr, min_max) {
var retval, i, len;
for(i=0,len=my_arr.length; i < len; i++) {
if (min_max == 'minimum') {
retval = (my_arr[i] < retval ? my_arr[i] : retval);
} else {
retval = (my_arr[i] > retval ? my_arr[i] : retval);
}
}
return retval;
}
Then you would call it like this:
console.log(extremeValue(vector, 'maximum'));
console.log(extremeValue(vector, 'minimum'));

Without the Built in Math Min/Max method:
let minMaxValues = (arr) => {
let maxValues;
let minValues;
for (let i = 0; i < arr.length; i++) {
// check first value with all iterater
if(arr[i] < arr[1]){
minValues = arr[i];
}
// check last value with all iterater
if(arr[i] > arr[arr.length-1]){
maxValues = arr[i];
}
}
console.log(minValues);
console.log(maxValues);
}
minMaxValues([100, 20, 30, 10, 50]);

Related

Find all sentence permutations with synonymous words? [duplicate]

This question already has answers here:
Cartesian product of multiple arrays in JavaScript
(35 answers)
Closed 1 year ago.
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.
Consider this data:
[[0,1], [0,1,2,3], [0,1,2]]
3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.
For example:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
And so on.
If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Any help would be much appreciated.
Here is a quite simple and short one using a recursive helper function:
function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}
Usage:
cartesian([0,1], [0,1,2,3], [0,1,2]);
To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.
I suggest a simple recursive generator function:
// JS
function* cartesianIterator(head, ...tail) {
const remainder = tail.length ? cartesianIterator(...tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}
// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));
You could take an iterative approach by building sub arrays.
var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
After doing a little research I discovered a previous related question:
Finding All Combinations of JavaScript array values
I've adapted some of the code from there so that it returns an array of arrays containing all of the permutations:
function(arraysToCombine) {
var divisors = [];
for (var i = arraysToCombine.length - 1; i >= 0; i--) {
divisors[i] = divisors[i + 1] ? divisors[i + 1] * arraysToCombine[i + 1].length : 1;
}
function getPermutation(n, arraysToCombine) {
var result = [],
curArray;
for (var i = 0; i < arraysToCombine.length; i++) {
curArray = arraysToCombine[i];
result.push(curArray[Math.floor(n / divisors[i]) % curArray.length]);
}
return result;
}
var numPerms = arraysToCombine[0].length;
for(var i = 1; i < arraysToCombine.length; i++) {
numPerms *= arraysToCombine[i].length;
}
var combinations = [];
for(var i = 0; i < numPerms; i++) {
combinations.push(getPermutation(i, arraysToCombine));
}
return combinations;
}
I've put a working copy at http://jsfiddle.net/7EakX/ that takes the array you gave earlier ([[0,1], [0,1,2,3], [0,1,2]]) and outputs the result to the browser console.
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
console.log(charSet.reduce((a,b)=>a.flatMap(x=>b.map(y=>x+y)),['']))
Just for fun, here's a more functional variant of the solution in my first answer:
function cartesian() {
var r = [], args = Array.from(arguments);
args.reduceRight(function(cont, factor, i) {
return function(arr) {
for (var j=0, l=factor.length; j<l; j++) {
var a = arr.slice(); // clone arr
a[i] = factor[j];
cont(a);
}
};
}, Array.prototype.push.bind(r))(new Array(args.length));
return r;
}
Alternative, for full speed we can dynamically compile our own loops:
function cartesian() {
return (cartesian.cache[arguments.length] || cartesian.compile(arguments.length)).apply(null, arguments);
}
cartesian.cache = [];
cartesian.compile = function compile(n) {
var args = [],
indent = "",
up = "",
down = "";
for (var i=0; i<n; i++) {
var arr = "$"+String.fromCharCode(97+i),
ind = String.fromCharCode(105+i);
args.push(arr);
up += indent+"for (var "+ind+"=0, l"+arr+"="+arr+".length; "+ind+"<l"+arr+"; "+ind+"++) {\n";
down = indent+"}\n"+down;
indent += " ";
up += indent+"arr["+i+"] = "+arr+"["+ind+"];\n";
}
var body = "var res=[],\n arr=[];\n"+up+indent+"res.push(arr.slice());\n"+down+"return res;";
return cartesian.cache[n] = new Function(args, body);
}
var f = function(arr){
if(typeof arr !== 'object'){
return false;
}
arr = arr.filter(function(elem){ return (elem !== null); }); // remove empty elements - make sure length is correct
var len = arr.length;
var nextPerm = function(){ // increase the counter(s)
var i = 0;
while(i < len)
{
arr[i].counter++;
if(arr[i].counter >= arr[i].length){
arr[i].counter = 0;
i++;
}else{
return false;
}
}
return true;
};
var getPerm = function(){ // get the current permutation
var perm_arr = [];
for(var i = 0; i < len; i++)
{
perm_arr.push(arr[i][arr[i].counter]);
}
return perm_arr;
};
var new_arr = [];
for(var i = 0; i < len; i++) // set up a counter property inside the arrays
{
arr[i].counter = 0;
}
while(true)
{
new_arr.push(getPerm()); // add current permutation to the new array
if(nextPerm() === true){ // get next permutation, if returns true, we got them all
break;
}
}
return new_arr;
};
Here's another way of doing it. I treat the indices of all of the arrays like a number whose digits are all different bases (like time and dates), using the length of the array as the radix.
So, using your first set of data, the first digit is base 2, the second is base 4, and the third is base 3. The counter starts 000, then goes 001, 002, then 010. The digits correspond to indices in the arrays, and since order is preserved, this is no problem.
I have a fiddle with it working here: http://jsfiddle.net/Rykus0/DS9Ea/1/
and here is the code:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));
You can use a recursive function to get all combinations
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '', final = []) => {
if (arr.length > 1) {
arr[0].forEach(v => loopOver(arr.slice(1), str + v, final))
} else {
arr[0].forEach(v => final.push(str + v))
}
return final
}
console.log(loopOver(charSet))
This code can still be shorten using ternary but i prefer the first version for readability 😊
const charSet = [["A", "B"],["C", "D", "E"],["F", "G", "H", "I"]];
let loopOver = (arr, str = '') => arr[0].map(v => arr.length > 1 ? loopOver(arr.slice(1), str + v) : str + v).flat()
console.log(loopOver(charSet))
Another implementation with ES6 recursive style
Array.prototype.cartesian = function(a,...as){
return a ? this.reduce((p,c) => (p.push(...a.cartesian(...as).map(e => as.length ? [c,...e] : [c,e])),p),[])
: this;
};
console.log(JSON.stringify([0,1].cartesian([0,1,2,3], [[0],[1],[2]])));

How to find number of occurrence of highest element in an Javascript Array?

function findMaxOccurence(ar){
ar.sort().reverse() // Reverses a sorted array Max to min
count = 0;
for(i=0;i<ar.length;i++){
++count
if(i == ar.length - 1){//break out when last element reached
break
}
if(ar[i+1] != ar[i]){
break
}
}
return count
}
How to find number of occurrence of highest element in an Javascript Array ?
You can use reduce method in order to write a more easy solution.
The reduce() method applies a function against an accumulator and each
element in the array (from left to right) to reduce it to a single
value.
let dataset = [2,8,4,8,6,4,7,8];
let max= Math.max(...dataset);
var count = dataset.reduce(function(counter, value) {
return counter + (value === max);
}, 0);
console.log(count);
Also, you can use filter method by passing a callback function.
let count = dataset.filter(x => x === max).length;
Find the below two methods:
function findMaxOccurence(ar){
ar.sort().reverse(); // Reverses a sorted array Max to min
var count = 1;
for(var i = 1; i < ar.length; i++){
if(ar[i] == ar[0])
count++;
}
return count
}
function findMaxOccurence(ar){
ar.sort().reverse(); // Reverses a sorted array Max to min
var count = 1;
for(var i = 1; i < ar.length; i++){
if(ar[i] != ar[0])
break;
count++;
}
return count
}
You could use Array#reduce in a single loop with an object as temporary result set.
function findMaxOccurence(array) {
return array.reduce(function(r, a) {
if (!r || a > r.value) {
return { value: a, count: 1 };
}
if (r.value === a) {
r.count++;
}
return r;
}, undefined).count;
}
console.log(findMaxOccurence([1, 3, 4, 2, 4, 2, 1, 3]));
You can use both these solutions provided below, just remember that the filter solution is a bit faster ^^
//Code
let dataset = [2,8,4,8,6,4,7,8];
let t0 = performance.now();
countWithReduce(dataset);
let t1 = performance.now();
console.log("Call to countWithReduce took " + (t1 - t0) + " milliseconds.")
t0 = performance.now();
countWithFilter(dataset);
t1 = performance.now();
console.log("Call to countWithFilter took " + (t1 - t0) + " milliseconds.")
//Functions
function countWithReduce(arr){
let max= Math.max(...arr);
let count = arr.reduce(function(counter, value) {
return counter + (value === max);
}, 0);
console.log(count);
}
function countWithFilter(arr){
let max= Math.max(...arr);
let count = arr.filter(x => x === max).length;
console.log(count);
}
function findMaxOccurence(ar){
ar.sort((a, b) => b - a);
let count = 0;
for(let i = 0; i < ar.length; i++){
if(ar[i] === ar[0]){
count++;
}
}
return count;
}
So, basically what I did with this solution is use the sort((a, b) => a - b) method.
This sorts the array in descending order, which is the most effective in case you're dealing with bigger numbers (for example 102, 113, etc.) for which the reverse method will not be effective.
Then create a count variable to keep track of the number of occurence of the maximum element in the array.
Then run a for loop and compare the elements in the index of ar[i] and add to the count, if that element is equal to ar[0], which will be the maximum element after rearranging the elements in descending order.

Javascript reduce() until sum of values < variable

I am fetching an array of video durations (in seconds) from a JSON file in Javascript, that, to simplify, would look like this:
array = [30, 30, 30]
I would like to add each value to the previous value until a condition is met (the sum being less than a variable x) and then to get both the new value and the index position in the array of the video to play.
For example if x=62 (condition), I would like the first two values in the array to be added (from my understanding reduce() is appropriate here), and the index = 2 (the second video in the array).
I've got the grasp of reduce():
var count = array.reduce(function(prev, curr, index) {
console.log(prev, curr, index);
return prev + curr;
});
But can't seem to get beyond this point.. Thanks
You could use Array#some, which breaks on a condition.
var array = [30, 30, 30],
x = 62,
index,
sum = 0;
array.some(function (a, i) {
index = i;
if (sum + a > x) {
return true;
}
sum += a;
});
console.log(index, sum);
With a compact result and this args
var array = [30, 30, 30],
x = 62,
result = { index: -1, sum: 0 };
array.some(function (a, i) {
this.index = i;
if (this.sum + a > x) {
return true;
}
this.sum += a;
}, result);
console.log(result);
var a = [2,4,5,7,8];
var index;
var result = [0, 1, 2, 3].reduce(function(a, b,i) {
var sum = a+b;
if(sum<11){
index=i;
return sum;
}
}, 2);
console.log(result,index);
What about using a for loop? This is hack-free:
function sumUntil(array, threshold) {
let i
let result = 0
// we loop til the end of the array
// or right before result > threshold
for(i = 0; i < array.length && result+array[i] < threshold; i++) {
result += array[i]
}
return {
index: i - 1, // -1 because it is incremented at the end of the last loop
result
}
}
console.log(
sumUntil( [30, 30, 30], 62 )
)
// {index: 1, result: 60}
bonus: replace let with var and it works on IE5.5
You could do
var limit = 60;
var array = [30,30,30];
var count = array.reduce(function(prev, curr, index) {
var temp = prev.sum + curr;
if (index != -1) {
if (temp > limit) {
prev.index = index;
} else {
prev.sum = temp;
}
}
return prev;
}, {
sum: 0,
index: -1
});
console.log(count);
What about this : https://jsfiddle.net/rtcgpgk2/1/
var count = 0; //starting index
var arrayToCheck = [20, 30, 40, 20, 50]; //array to check
var condition = 100; //condition to be more than
increment(arrayToCheck, count, condition); //call function
function increment(array, index, conditionalValue) {
var total = 0; //total to add to
for (var i = 0; i < index; i++) { //loop through array up to index
total += array[i]; //add value of array at index to total
}
if (total < conditionalValue) { //if condition is not met
count++; //increment index
increment(arrayToCheck, count, condition); //call function
} else { //otherwise
console.log('Index : ', count) //log what index condition is met
}
}
// define the max outside of the reduce
var max = 20;
var hitIndex;
var count = array.reduce(function(prev, curr, index) {
let r = prev + curr;
// if r is less than max keep adding
if (r < max) {
return r
} else {
// if hitIndex is undefined set it to the current index
hitIndex = hitIndex === undefined ? index : hitIndex;
return prev;
}
});
console.log(count, hitIndex);
This will leave you with the index of the first addition that would exceed the max. You could try index - 1 for the first value that did not exceed it.
You can create a small utility method reduceWhile
// Javascript reduceWhile implementation
function reduceWhile(predicate, reducer, initValue, coll) {
return coll.reduce(function(accumulator, val) {
if (!predicate(accumulator, val)) return accumulator;
return reducer(accumulator, val);
}, initValue)
};
function predicate(accumulator, val) {
return val < 6;
}
function reducer(accumulator, val) {
return accumulator += val;
}
var result = reduceWhile(predicate, reducer, 0, [1, 2, 3, 4, 5, 6, 7])
console.log("result", result);

Generate permutations of JavaScript array [duplicate]

This question already has answers here:
Permutations in JavaScript?
(41 answers)
Closed 1 year ago.
I have an array of n different elements in javascript, I know there are n! possible ways to order these elements. I want to know what's the most effective (fastest) algorithm to generate all possible orderings of this array?
I have this code:
var swap = function(array, frstElm, scndElm) {
var temp = array[frstElm];
array[frstElm] = array[scndElm];
array[scndElm] = temp;
}
var permutation = function(array, leftIndex, size) {
var x;
if(leftIndex === size) {
temp = "";
for (var i = 0; i < array.length; i++) {
temp += array[i] + " ";
}
console.log("---------------> " + temp);
} else {
for(x = leftIndex; x < size; x++) {
swap(array, leftIndex, x);
permutation(array, leftIndex + 1, size);
swap(array, leftIndex, x);
}
}
}
arrCities = ["Sidney", "Melbourne", "Queenstown"];
permutation(arrCities, 0, arrCities.length);
And it works, but I guess swapping every item to get the combinations is a bit expensive memory wise, I thought a good way of doing it is just focusing on the indexes of the array and getting all the permutations of the numbers, I'm wondering if there's a way of computing all of them without having to switch elements within the array? I guess recursively is possible to get all of them, I need help to do so.
So for example if I have:
arrCities = ["Sidney", "Melbourne", "Queenstown"];
I want the output to be:
[[012],[021],[102],[120],[201],[210]]
or:
[[0,1,2],
[0,2,1],
[1,0,2],
[1,2,0],
[2,0,1],
[2,1,0]]
I'm reading this:
http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations
But Wikipedia has never been good at explaining. I don't understand much of it, I have to say my math level isn't the best.
This function, perm(xs), returns all the permutations of a given array:
function perm(xs) {
let ret = [];
for (let i = 0; i < xs.length; i = i + 1) {
let rest = perm(xs.slice(0, i).concat(xs.slice(i + 1)));
if(!rest.length) {
ret.push([xs[i]])
} else {
for(let j = 0; j < rest.length; j = j + 1) {
ret.push([xs[i]].concat(rest[j]))
}
}
}
return ret;
}
console.log(perm([1,2,3]).join("\n"));
Using Heap's method (you can find it in this paper which your Wikipedia article links to), you can generate all permutations of N elements with runtime complexity in O(N!) and space complexity in O(N). This algorithm is based on swapping elements. AFAIK this is as fast as it gets, there is no faster method to calculate all permutations.
For an implementation and examples, please have a look at my recent answer at the related question "permutations in javascript".
It is just for fun - my recursive solve in one string
const perm = a => a.length ? a.reduce((r, v, i) => [ ...r, ...perm([ ...a.slice(0, i), ...a.slice(i + 1) ]).map(x => [ v, ...x ])], []) : [[]]
This is my version based on le_m's code:
function permute(array) {
Array.prototype.swap = function (index, otherIndex) {
var valueAtIndex = this[index]
this[index] = this[otherIndex]
this[otherIndex] = valueAtIndex
}
var result = [array.slice()]
, length = array.length
for (var i = 1, heap = new Array(length).fill(0)
; i < length
;)
if (heap[i] < i) {
array.swap(i, i % 2 && heap[i])
result.push(array.slice())
heap[i]++
i = 1
} else {
heap[i] = 0
i++
}
return result
}
console.log(permute([1, 2, 3]))
This is my recursive JavaScript implementation of the same algorithm:
Array.prototype.swap = function (index, otherIndex) {
var valueAtIndex = this[index]
this[index] = this[otherIndex]
this[otherIndex] = valueAtIndex
}
Array.prototype.permutation = function permutation(array, n) {
array = array || this
n = n || array.length
var result = []
if (n == 1)
result = [array.slice()]
else {
const nextN = n - 1
for (var i = 0; i < nextN; i++) {
result.push(...permutation(array, nextN))
array.swap(Number(!(n % 2)) && i, nextN)
}
result.push(...permutation(array, nextN))
}
return result
}
console.log([1, 2, 3].permutation())
function permutations(str) {
return (str.length <= 1) ? [str] :
Array.from(new Set(
str.split('')
.map((char, i) => permutations(str.substr(0, i) + str.substr(i + 1)).map(p => char + p))
.reduce((r, x) => r.concat(x), [])
));
}

How to find the max/min of a nested array in javascript?

I want to find the maximum of a nested array, something like this:
a = [[1,2],[20,3]]
d3.max(d3.max(a)) // 20
but my array contains a text field that I want to discard:
a = [["yz",1,2],["xy",20,3]]
d3.max(a) // 20
If you have a nested array of numbers (arrays = [[1, 2], [20, 3]]), nest d3.max:
var max = d3.max(arrays, function(array) {
return d3.max(array);
});
Or equivalently, use array.map:
var max = d3.max(arrays.map(function(array) {
return d3.max(array);
}));
If you want to ignore string values, you can use array.filter to ignore strings:
var max = d3.max(arrays, function(array) {
return d3.max(array.filter(function(value) {
return typeof value === "number";
}));
});
Alternatively, if you know the string is always in the first position, you could use array.slice which is a bit more efficient:
var max = d3.max(arrays, function(array) {
return d3.max(array.slice(1));
});
Yet another option is to use an accessor function which returns NaN for values that are not numbers. This will cause d3.max to ignore those values. Conveniently, JavaScript's built-in Number function does exactly this, so you can say:
var max = d3.max(arrays, function(array) {
return d3.max(array, Number);
});
Use this:
function arrmax(arrs) {
var toplevel = [];
var f = function(v) {
return !isNaN(v);
};
for (var i = 0, l = arrs.length; i<l; i++) {
toplevel.push(Math.max.apply(window, arrs[i].filter(f)));
}
return Math.max.apply(window, toplevel);
}
or better:
function arrmax(arrs) {
if (!arrs || !arrs.length) return undefined;
var max = Math.max.apply(window, arrs[0]), m,
f = function(v){ return !isNaN(v); };
for (var i = 1, l = arrs.length; i<l; i++) {
if ((m = Math.max.apply(window, arrs[i].filter(f)))>max) max=m;
}
return max;
}
See MDN for Array.filter method details.
If you now exactly what columns you want to test, you can use:
var columns = ["ColumnA", "ColumnB", "ColumnC"];
var max = selectedMax(columns,dataset);
var min = selectedMin(columns,dataset)
function selectedMax(columns, dataset) {
var max;
columns.forEach(function(element, index, array) {
var tmpmax = d3.max(dataset, function(d) {
return +d[element];
});
max = (tmpmax > max || max === undefined) ? tmpmax : max;
});
return max;
}
function selectedMin(columns, dataset) {
var min;
columns.forEach(function(element, index, array) {
var tmpmin = d3.min(dataset, function(d) {
return +d[element];
});
min = (tmpmin < min || min === undefined) ? tmpmin : min;
});
return min;
}
You can flatten an array and apply a function to each member
Array.prototype.flatten= function(fun){
if(typeof fun!= 'function') fun= '';
var A= [], L= this.length, itm;
for(var i= 0; i<L; i++){
itm= this[i];
if(itm!= undefined){
if(!itm.flatten){
if(fun) itm= fun(itm);
if(itm) A.push(itm);
}
else A= A.concat(itm.flatten(fun));
}
}
return A;
}
var a= [["yz", 1, 2], ["xy", 20, 3]], max=-Infinity;
var max=Math.max.apply(a, a.flatten(Number));
It's a cruel hack, but looking at the source code for d3.max, your best bet might be to define a d3.max1 that discards the first element by copying that code, but replacing i=-1 with i=0. The code at that link is excerpted here. Note that I'm not a regular d3.js user, but from what I know of the library, you're going to want make sure your version has an f.call case like this function does, so that it can respond to live updates correctly.
d3.max = function(array, f) {
var i = -1,
n = array.length,
a,
b;
if (arguments.length === 1) {
while (++i < n && ((a = array[i]) == null || a != a)) a = undefined;
while (++i < n) if ((b = array[i]) != null && b > a) a = b;
} else {
while (++i < n && ((a = f.call(array, array[i], i)) == null || a != a)) a = undefined;
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
}
return a;
};
Then it would just be d3.max(d3.max1(a)).
d3.array provides d3.merge which flattens an array of arrays.
Coupled with d3.max and javascript's Number as an accessor:
var max = d3.max(d3.merge(arrays), Number);
For example:
var input = [["yz", 1, 2], ["xy", 20, 3]];
var max = d3.max(d3.merge(input), Number);
console.log(max);
<script src="https://d3js.org/d3-array.v2.min.js"></script>

Categories

Resources