So I have a spreadsheet for retrieving membership rates, the columns are Age, Duration & Rate. You simply look down the age column to find the age of the customer, then when you find that age you keep heading down to match it to the correct Duration, then in the final column will be the rate. A (very) small version of that might look like this;
Age,Duration,Rate
18,10,1.33
18,11,1.5
18,12,1.8
19,10,1.4
19,11,1.65
19,12,1.88
20,10,1.48
20,11,1.73
20,12,1.98
So someone age 19, duration 11 has a rate of 1.65. Someone age 20 with a duration of 12 has a rate of 1.98 - easy!
My question is two parts, I want to convert this into a web page where someone enters the age and duration to retrieve the rate. I'm pretty sure my best option for this is a two dimensional array like so;
var array = [[18,10,1.33],[18,11,1.5],[18,12,1.8] .. and so on];
are there any better options for this?
The second question is how do I best iterate over a two dimensional array (if that ends up being the best solution)? As I touched upon before I would need to be able to have an iteration that returns the rate based on a two criteria search. I believe this would consist of a two part iteration but iteration is such a weak spot for me that trying to grasp where in the loops to put my iterations is just brain melting. I think it would look something like so;
for (var i = 0; i < array.length; i++){
for (var j = 0; j < array[i].length; j++){
//Do something... I think something like this
If array[][j] == ageImLookingFor && array[][j+1] == durationImLookingFor
then return array[][j+2] (which is the rate)
}
}
Any help, advice or ideas I would be super grateful
A better option than using an array is to use an object (or Map) with properties (keys) that correspond to valid combinations of age and duration, effectively indexing your data by that key:
var list = {
'18_10': { age: 18, duration: 10, rate: 1.33 }
'18_11': { age: 18, duration: 11, rate: 1.5 },
'18_12': { age: 18, duration: 11, rate: 1.8 },
// .. and so on
};
This way you do not have to iterate over an array (cf. your question #2), but given an age and a duration (let's say in variables that have those names), you can write this to get the matching item:
var item = list[age + '_' + duration];
Of course, you should check that age and duration are valid integer numbers and that the item could be undefined when the combination is not known.
Here is a simple snippet (without any checks) you could use to base your web form on. It builds the above mentioned object from an array having the data.
// Data in array -- will be keyed later
var arr = [
{ age: 18, duration: 10, rate: 1.33 },
{ age: 18, duration: 11, rate: 1.5 },
{ age: 18, duration: 12, rate: 1.8 },
{ age: 19, duration: 10, rate: 1.4 },
{ age: 19, duration: 11, rate: 1.65 },
{ age: 19, duration: 12, rate: 1.33 },
{ age: 20, duration: 10, rate: 1.48 },
{ age: 20, duration: 11, rate: 1.73 },
{ age: 20, duration: 12, rate: 1.98 },
];
// Build map, keyed by age/duration. It will look like:
// {
// '18_10': { age: 18, duration: 10, rate: 1.33 },
// '18_11': { age: 18, duration: 11, rate: 1.33 },
// ...etc
// }
mapByAgeDuration = {};
for (var i=0; i < arr.length; i++) {
mapByAgeDuration[arr[i].age + '_' + arr[i].duration] = arr[i];
}
// Fast retrieval function:
function getItemFor(age, duration) {
return mapByAgeDuration[age + '_' + duration];
}
// I/O
var button = document.getElementById('findRate');
var inputAge = document.getElementById('age');
var inputDuration = document.getElementById('duration');
var outputRate = document.getElementById('rate');
button.onclick = function() {
var age = inputAge.value;
var duration = inputDuration.value;
// Retrieve item for this age and duration
var item = getItemFor(age, duration);
// Output rate
outputRate.textContent = item !== undefined ? item.rate
: 'not a valid combination';
}
Age (18 - 20): <input id="age"><br>
Duration (10 - 12): <input id="duration"><br>
<button id="findRate">Find Rate</button><br>
Rate: <span id="rate"></span><br>
Q1: You can use a hash table for your lookup.
var data = [[18, 10, 1.33], [18, 11, 1.5], [18, 12, 1.8], [19, 10, 1.4], [19, 11, 1.65], [19, 12, 1.88], [20, 10, 1.48], [20, 11, 1.73], [20, 12, 1.98]],
object = {};
data.forEach(function (a) {
object[a[0]] = object[a[0]] || {};
object[a[0]][a[1]] = a[2];
});
// usage
document.write(object[19][11] + '<br>');
document.write(object[20][12] + '<br>');
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
Q2: A proposal with Array#some()
If you have sorted data, you could insert a short circuit, if the values are greater then needed.
var data = [[18, 10, 1.33], [18, 11, 1.5], [18, 12, 1.8], [19, 10, 1.4], [19, 11, 1.65], [19, 12, 1.88], [20, 10, 1.48], [20, 11, 1.73], [20, 12, 1.98]],
object = {};
function getValue(p1, p2) {
var result;
data.forEach(function (a) {
if (a[0] === p1 && a[1] === p2) {
result = a[2];
return true;
}
// short circuit for not found values
return a[0] > p1;
});
return result;
}
// usage
document.write(getValue(19, 11) + '<br>');
document.write(getValue(20, 12) + '<br>');
Another approach is to leverage on the array.filter function.
You have to reshape your data into an objects array:
var rates = [
{'age':'18','duration':'10','rate':'1.33'},
{'age':'18','duration':'11','rate':'1.5'},
{'age':'19','duration':'12','rate':'1.8'}
];
function filterRate(item){
if(item.age == this.age && item.duration == this.duration)
return item;
}
function getRateByAgeDuration(age, duration){
res = null;
try{
res = rates.filter(filterRate, {'age':age, 'duration':duration})[0].rate;
}
catch(ex){ console.log(ex);}
return res;
}
document.write(getRateByAgeDuration('18', '10'));
It depends. If you use hashes, you will have O(1) time on average, but O(n) on worst case.
If you prefer to optimize the worst case, you can use binary search to achieve O(lg n) both on average and worst cases.
function binarySearch(array, data, from=0, to=array.length) {
if(from >= to) return -1; // not found
var m = Math.floor((from+to)/2);
for(var i=0; i<data.length; ++i) {
if(data[i] < array[m][i]) return binarySearch(array, data, from, m);
if(data[i] > array[m][i]) return binarySearch(array, data, m+1, to);
}
return m;
}
var idx = binarySearch(array, [18,12]);
if(idx > -1) array[idx];
Related
I was given this problem at one of my interviews and was told I have 20 minutes to solve it. This is the answer I came up with ( 2 versions ). Can you let me know which version you prefer and why, and if you have a better idea of how to solve it (less complex, less memory usage, etc.) Please share.
Problem: You have an array of random numbers that range from 0 to 100 elements.
Write a function that will split this array into several arrays, each containing elements in the following range: (0-10],(10-20],(20-30], etc up to a 100].
Write a function that outputs these arrays in a form of a simple graph, where each delimiter represents a single value in the array.
Array = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55,
65, 42, 99, 4];
Desired outcome:
5 Elements in array: ***** - 1,5,6,3,4
3 Elements in array: *** - 10,12,11
2 Elements in array: ** - 22,21
No Elements in array.
2 Elements in array: ** - 45,42
3 Elements in array: *** - 52,51,55
2 Elements in array: ** - 64,65
1 Elements in array: * - 71
No Elements in array.
2 Elements in array: ** - 95,99
// Version 1
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const splitArray = (inputArray, range) => {
const newArray = [];
do {
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
range += 10;
newArray.push(tempArray);
} while (range + 10 <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
let toPrint = "";
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
toPrint += stars
? `${stars} Elements in array: ${string} - ${array[index]} \n`
: "No Elements in array. \n";
}
return toPrint;
};
console.log(printArrays(splitArray(arr, 0), "*"));
// Version 2
arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const newArray = [];
let min = 0;
let max = 10;
do {
const tempArray = [];
for (i in arr) {
let val = arr[i];
val >= min && val < max ? tempArray.push(val) : "";
}
min += 10;
max += 10;
newArray.push(tempArray);
} while (max <= 100);
return newArray;
};
const printArrays = (array, delimiter) => {
for (index in array) {
let stars = array[index].length;
let string = "";
for (let i = stars; i > 0; i--) {
string += delimiter;
}
console.log(
stars ? `${stars} Elements in array: ${string} - ${array[index]}` : "No Elements in array."
);
}
};
printArrays(getArrays(arr), "^");
Both approaches have moderate issues.
The first approach does
let tempArray = [];
tempArray = inputArray.filter((item) => {
if (item >= range && item < range + 10) return item;
});
Better to just declare the tempArray as the filtered array to begin with.
const tempArray = inputArray.filter(...
Also, return item is suspicious inside a filter - all the filter callback cares about is whether its return value is truthy or falsey. Returning the array item when you actually want to indicate that the value should be included in the output is a common mistake. It happens not to be a problem here because 0 isn't a possibility, but it's still confusing. A better choice would be to do
const tempArray = inputArray.filter(
item => item >= range && item < range + 10
);
(and maybe rename range to startOfRange)
Both of your approaches are also iterating through the entire input array multiple times (once for each range), which seems a bit wasteful - better to iterate through the input once.
Your second approach uses for (i in arr), and both approaches are doing for (index in array). This is a bad idea, and since you don't actually care about the index you're iterating over, it'd make sense to use for..of loops instead.
I think a better looking approach that iterates through the input just once would be:
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
const getArrays = (inputArray) => {
const grouped = {};
for (let i = 0; i < 100; i += 10) {
grouped[i] = [];
}
for (const item of inputArray) {
const rangeProp = Math.floor(item / 10) * 10;
grouped[rangeProp].push(item);
}
return Object.values(grouped);
};
const printArrays = (groupedArrays, delimiter) => {
for (const array of groupedArrays) {
const stars = delimiter.repeat(array.length);
console.log(
stars
? `${array.length} Elements in array: ${stars} - ${array.join(',')}`
: "No Elements in array."
);
}
};
printArrays(getArrays(arr), "*");
I will do that this way :
This approach is simple: it retrieves the values one by one and adds them to the array corresponding to their range.
const arr = [10, 12, 71, 52, 51, 1, 5, 22, 21, 6, 95, 11, 3, 64, 45, 55, 65, 42, 99, 4];
let ranges = arr.reduce((a,x)=>
{
let range = (x/10)|0 // get range start value 0 to 9
a[range] ??= [] // create the array of if it does not already exist
a[range].push(x)
return a
},{})
console.log('ranges=', ranges ) // so that noobs can visualize this result
for (let r = 0; r < 10; r++ )
{
if (!ranges[r])
document.write('No Elements in array.<br>')
else
{
let count = ranges[r].length
document.write(`${count} Elements in array: ${'*'.repeat(count)} - ${ranges[r].join(',')}<br>`)
}
}
.as-console-wrapper {max-height: 100% !important; width:20%; top: 0;
margin-left: 80%; }
.as-console-row::after {display: none !important;}
range = (x/10)|0 // get range start value 0 to 9
example in case of x = 25 -> 25/10 give 2.5 and 2.5 | 0 give 2 -> integer part value of 2.5
| is the OR boolean operator, work only on integers values so it return an interger
??= is Logical nullish assignment
I'm looking for an easy way to do the following:
I have an array of random numbers between 0-99. I need two arrays, first which have values which share the same first digit, second for values that share the same second digit. It doesn't matter what that digit is, as long as it occurs more than once. 0-9 is to be treated as if the first digit was 0.
To illustrate the problem:
[0, 10, 20, 11, 19, 12, 54, 64, 23, 24] would result in [10, 11, 12, 19, 23, 24] and [0, 10, 20, 24, 54, 64]. Some values can go in both arrays if they meet the criteria.
I've found solutions that are useful if you know the digit you're comparing. However, not in this scenario.
I know the way to begin is to convert numbers inside the array into strings: array.map(String), so that the second and first digit can be accessed by first[0], second[1]. I don't know how to proceed from there, though. Any ideas are greatly appreciated.
You can group your array based on first digit and last digit in an object accumulator. Then, filter the grouped array based on length.
const input = [0, 10, 20, 11, 19, 12, 54, 64, 23, 24],
groupLastDigits = input.reduce((r, n) => {
const last = n % 10;
r[last] ??= [];
r[last].push(n);
return r;
}, {}),
groupFirstDigits = input.reduce((r, n) => {
let first = Math.floor(n / 10);
if(first === n) first = 0;
r[first] ??= [];
r[first].push(n);
return r;
}, {}),
getNumbers = o => Object.values(o).filter(arr => arr.length > 1).flat()
commonLastDigits = getNumbers(groupLastDigits),
commonFirstDigits = getNumbers(groupFirstDigits);
console.log(commonLastDigits);
console.log(commonFirstDigits);
I'd like to offer a generic solution for n digits!
let matchingDigitGroups = function*(arr) {
// Note that very large numbers will convert to string
// in scientific notation, breaking this approach
let maxDigits = Math.max(...arr.map(num => `${num}`.length));
let strs = arr.map(num => {
let str = `${num}`;
while (str.length < maxDigits) str = `0${str}`;
return str;
});
for (let i = 0; i < maxDigits; i++) {
let result = [];
for (let n = 0; n <= 9; n++) {
let matchDigits = strs.filter(str => str[i] === `${n}`);
if (matchDigits.length > 1) result.push(...matchDigits);
}
yield result;
}
};
let tests = [
[ 0, 10, 20, 11, 19, 12, 54, 64, 23, 24 ],
[ 100, 200, 300 ],
[ 111, 222, 333, 771, 828, 399 ],
[],
[ 1 ],
[ 92929, 91919 ]
];
for (let arr of tests) {
console.log(`Groups for: [ ${arr.join(', ')} ]`);
for (let group of matchingDigitGroups(arr)) console.log(` [ ${group.join(', ')} ]`);
}
Actually I have made this on excel using Vlookup but now I am making this on webpage.
I have a input box where user will enter the value
<input class="text" type="text" name="rawScore" onchange="calcpercentile()">
and I have a span of where user can get the result
<span id="percentile"></span>
I have two arrays
var percentile = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var rawScores = [1, 3, 5, 7, 10, 12, 18, 25, 27];
what code should I write that if I write so I get the
input value
(rawScores) (percentile)
1 10
2 20
3 30
4 40
Your example seems wrong. I expect score 1 to map to the 10th percentile, 2 & 3 to the 20th percentile, and 4 to the 30th percentile.
In essence, I think what you're trying to do is: find the array index of the first raw score that is greater than the input, and return the corresponding value from the percentiles array.
The Javascript could look something like this:
var percentiles = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var rawScores = [1, 3, 5, 7, 10, 12, 18, 25, 27];
function map(input) {
let index = rawScores.findIndex(rawScore => rawScore >= input);
return percentiles[index];
}
console.log(map(1));
console.log(map(2));
console.log(map(3));
console.log(map(4));
Note that browser support for Array#findIndex() is limited. If you need wide browser support, a simple loop-based approach might be better:
var percentiles = [10, 20, 30, 40, 50, 60, 70, 80, 90];
var rawScores = [1, 3, 5, 7, 10, 12, 18, 25, 27];
function map(input) {
for (var i = 0; i < rawScores.length; i++) {
if (rawScores[i] >= input) {
return percentiles[i];
}
}
}
console.log(map(1));
console.log(map(2));
console.log(map(3));
console.log(map(4));
you can input text : 1
span display "10"
window.onload = function(){
var percentile = [0,10, 20, 30, 40, 50, 60, 70, 80, 90];
document.getElementById("rawScore").onchange = function () {
var index = document.getElementById("rawScore").value;
document.getElementById("percentile").innerHTML = percentile[index];
}
}
<input class="text" type="text" id="rawScore">
<span id="percentile"></span>
First you sort your dataset of course
const arr = [0,2,5,2,7,3];
const data = arr.sort();
What may help next, is this function to find the index of the closest number.
console.log(findClosestIndex([0, 1, 2, 3.5, 4.5, 5], 4));
// output: 3
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 4));
// output: 4
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], 90));
// output: 5
console.log(findClosestIndex([0, 1, 2, 3.49, 4.5, 5], -1));
// output: 0
function findClosestIndex(arr, element) {
let from = 0, until = arr.length - 1
while (true) {
const cursor = Math.floor((from + until) / 2);
if (cursor === from) {
const diff1 = element - arr[from];
const diff2 = arr[until] - element;
return diff1 <= diff2 ? from : until;
}
const found = arr[cursor];
if (found === element) return cursor;
if (found > element) {
until = cursor;
} else if (found < element) {
from = cursor;
}
}
}
So, now you know your index and the length of your array. And you have to get a percentile from that. Let's first calculate an exact percentage.
const index = findClosestIndex(data, input);
const pct = index / arr.length;
Turning this percentage into a percentile is a matter of rounding it.
const percentile = (Math.floor(pct/10)+1) * 10;
(PS: I use this function for buying/selling stocks when their current price is in a certain percentile of the daily transaction price rates.)
Sup fellow geeks!
I'm trying to make an array that lists all the possible values of the sums of the elements of an array. I'm sure this must be quite easy but I'm up to 2 or 3 hours now and I'm getting frustrated, I think I'm almost there...
var frootVals = [0,1,2,3,4,5]
var frootInc = frootVals
var fruitEnd = frootInc[frootInc.length-1]//begins at 5
var fruitAll = 15 // The total of all the numbers in the array. (this is actually
// calculated in another function, but lets just say I declared it as 15)
for (e = frootVals.length-2 ;fruitEnd !== fruitAll;e--){ //so I want it to
//finish when the final array entry is 15.
for (p = 1;p < e; p++){
var incEnd = frootInc[frootInc.length-p]
frootInc.push(incEnd + frootVals[p]) //1st time round (5 + 1 = 6, 5 + 2 = 7,
//5 + 3 =8, 5 + 4 = 9) THEN start again with 9 now being incEnd so pushes
//9+1 = 10 etc etc until the last digit is 15 and the whole loop stops...
}
}
EDIT - Basically the final result I'm after is frootInc to be be an array of the integers [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] - I'm sure I'll kick myself for giving up but I've only been learning a few weeks so this is all quite brain taxing.
After thinking about your question a bit, I think the easiest solution would be with recursion when the condition that the final value added to the array is less than the sum of values.
Here's a JS Fiddle for demo: http://jsfiddle.net/ukgzwpky/
To break it down a bit (and so that you may confirm I have the question right :D), say we have the following array:
[0, 1, 2, 3, 10, 15, 30]
The sum of the values are: 61. So the expected output array would be:
[0, 1, 2, 3, 10, 15, 30, 31, 32, 33, 40, 45, 46, 47, 48, 55, 60, 61]
To further break it down, the looping logic would do something like this:
// Get final value to add to previous values
var val = [0, 1, 2, 3, 10, 15, 30].pop();
// Add the final value - 30 - to all previous values (ignoring the zero)
.. loop here and push the values to our array ...
// For the first iteration, the updated array looks like:
[0, 1, 2, 3, 10, 15, 30, 31, 32, 33, 40, 45]
// New values calculated from: 30 + 1, 30 + 2, 30 + 3, 30 + 10, 30 + 15
At this point, our max value of 61 is less than the final value of 45 So, we do it again!
var val = [0, 1, 2, 3, 10, 15, 30, 31, 32, 33, 40, 45].pop();
.. loop here and push the values to our array ...
// Second iteration, the updated array looks like:
[0, 1, 2, 3, 10, 15, 30, 31, 32, 33, 40, 45, 46, 47, 48, 55, 60, 61]
// New values are: 45 + 1, 45 + 2, 45 + 3, 45 + 10, 45 + 15
// Note that 45 + 30 would be greater than our sum of 61, so we break
If that's correct, here's a script that I wrote that populates such an array:
function getPopulatedArray(arr) {
var max = arguments[1] || getSum(arr),
current = arr.pop(),
temp = [],
i = 1,
len = arr.length;
// Populate temp array with values
for (; i < len; i++) {
if ((arr[i] + current) < max) {
temp.push(arr[i] + current);
} else {
temp.push(max);
break;
}
}
arr.push(current);
arr = arr.concat(temp);
// Done? Or should we continue?
if (arr[arr.length - 1] < max) {
return getPopulatedArray(arr, max);
} else {
return arr;
}
}
Again, the JS fiddle for demonstration: http://jsfiddle.net/ukgzwpky/
Hopefully this helps!
A very simple solution would be to do something like this:
var frootVals = [0,1,2,3,4,5]
var result = [];
for (var i = 0; i < frootVals.length; i++){ // Iterate over the array twice
for (var j = 0; j < frootVals.length; j++){ // To calculate all combinations
result.push(frootVals[i] + frootVals[j]);
}
}
Now, if you don't want duplicates, try this:
var frootVals = [0,1,2,3,4,5]
var result = [];
for (var i = 0; i < frootVals.length; i++){
for (var j = 0; j < frootVals.length; j++){
var value = frootVals[i] + frootVals[j];
if(result.indexOf(value) === -1){
result.push(value);
}
}
}
You could then use result = result.sort() if you want to output a sorted result.
Array justPrices has values such as:
[0] = 1.5
[1] = 4.5
[2] = 9.9.
How do I return the smallest value in the array?
The tersest expressive code to find the minimum value is probably rest parameters:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = Math.min(...arr)
console.log(min)
Rest parameters are essentially a convenient shorthand for Function.prototype.apply when you don't need to change the function's context:
var arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
var min = Math.min.apply(Math, arr)
console.log(min)
This is also a great use case for Array.prototype.reduce:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
const min = arr.reduce((a, b) => Math.min(a, b))
console.log(min)
It may be tempting to pass Math.min directly to reduce, however the callback receives additional parameters:
callback (accumulator, currentValue, currentIndex, array)
In this particular case it may be a bit verbose. reduce is particularly useful when you have a collection of complex data that you want to aggregate into a single value:
const arr = [{name: 'Location 1', distance: 14}, {name: 'Location 2', distance: 58}, {name: 'Location 3', distance: 20}, {name: 'Location 4', distance: 77}, {name: 'Location 5', distance: 66}, {name: 'Location 6', distance: 82}, {name: 'Location 7', distance: 42}, {name: 'Location 8', distance: 67}, {name: 'Location 9', distance: 42}, {name: 'Location 10', distance: 4}]
const closest = arr.reduce(
(acc, loc) =>
acc.distance < loc.distance
? acc
: loc
)
console.log(closest)
And of course you can always use classic iteration:
var arr,
i,
l,
min
arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
min = Number.POSITIVE_INFINITY
for (i = 0, l = arr.length; i < l; i++) {
min = Math.min(min, arr[i])
}
console.log(min)
...but even classic iteration can get a modern makeover:
const arr = [14, 58, 20, 77, 66, 82, 42, 67, 42, 4]
let min = Number.POSITIVE_INFINITY
for (const value of arr) {
min = Math.min(min, value)
}
console.log(min)
Jon Resig illustrated in this article how this could be achieved by extending the Array prototype and invoking the underlying Math.min method which unfortunately doesn't take an array but a variable number of arguments:
Array.min = function( array ){
return Math.min.apply( Math, array );
};
and then:
var minimum = Array.min(array);
I find that the easiest way to return the smallest value of an array is to use the Spread Operator on Math.min() function.
return Math.min(...justPrices);
//returns 1.5 on example given
The page on MDN helps to understand it better: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min
A little extra:
This also works on Math.max() function
return Math.max(...justPrices);
//returns 9.9 on example given.
Hope this helps!
Update: use Darin's / John Resig answer, just keep in mind that you dont need to specifiy thisArg for min, so Math.min.apply(null, arr) will work just fine.
or you can just sort the array and get value #1:
[2,6,7,4,1].sort()[0]
[!] But without supplying custom number sorting function, this will only work in one, very limited case: positive numbers less than 10. See how it would break:
var a = ['', -0.1, -2, -Infinity, Infinity, 0, 0.01, 2, 2.0, 2.01, 11, 1, 1e-10, NaN];
// correct:
a.sort( function (a,b) { return a === b ? 0 : a < b ? -1: 1} );
//Array [NaN, -Infinity, -2, -0.1, 0, "", 1e-10, 0.01, 1, 2, 2, 2.01, 11, Infinity]
// incorrect:
a.sort();
//Array ["", -0.1, -2, -Infinity, 0, 0.01, 1, 11, 1e-10, 2, 2, 2.01, Infinity, NaN]
And, also, array is changed in-place, which might not be what you want.
Imagine you have this array:
var arr = [1, 2, 3];
ES6 way:
var min = Math.min(...arr); //min=1
ES5 way:
var min = Math.min.apply(null, arr); //min=1
If you using D3.js, there is a handy function which does the same, but will ignore undefined values and also check the natural order:
d3.max(array[, accessor])
Returns the maximum value in the given array using natural order. If
the array is empty, returns undefined. An optional accessor function
may be specified, which is equivalent to calling array.map(accessor)
before computing the maximum value.
Unlike the built-in Math.max, this method ignores undefined values;
this is useful for ignoring missing data. In addition, elements are
compared using natural order rather than numeric order. For example,
the maximum of the strings [“20”, “3”] is “3”, while the maximum of
the numbers [20, 3] is 20.
And this is the source code for D3 v4:
export default function(values, valueof) {
var n = values.length,
i = -1,
value,
max;
if (valueof == null) {
while (++i < n) { // Find the first comparable value.
if ((value = values[i]) != null && value >= value) {
max = value;
while (++i < n) { // Compare the remaining values.
if ((value = values[i]) != null && value > max) {
max = value;
}
}
}
}
}
else {
while (++i < n) { // Find the first comparable value.
if ((value = valueof(values[i], i, values)) != null && value >= value) {
max = value;
while (++i < n) { // Compare the remaining values.
if ((value = valueof(values[i], i, values)) != null && value > max) {
max = value;
}
}
}
}
}
return max;
}
ES6 is the way of the future.
arr.reduce((a, b) => Math.min(a, b));
I prefer this form because it's easily generalized for other use cases
var array =[2,3,1,9,8];
var minvalue = array[0];
for (var i = 0; i < array.length; i++) {
if(array[i]<minvalue)
{
minvalue = array[i];
}
}
console.log(minvalue);
Possibly an easier way?
Let's say justPrices is mixed up in terms of value, so you don't know where the smallest value is.
justPrices[0] = 4.5
justPrices[1] = 9.9
justPrices[2] = 1.5
Use sort.
justPrices.sort();
It would then put them in order for you. (Can also be done alphabetically.) The array then would be put in ascending order.
justPrices[0] = 1.5
justPrices[1] = 4.5
justPrices[2] = 9.9
You can then easily grab by the first index.
justPrices[0]
I find this is a bit more useful than what's proposed above because what if you need the lowest 3 numbers as an example? You can also switch which order they're arranged, more info at http://www.w3schools.com/jsref/jsref_sort.asp
function smallest(){
if(arguments[0] instanceof Array)
arguments = arguments[0];
return Math.min.apply( Math, arguments );
}
function largest(){
if(arguments[0] instanceof Array)
arguments = arguments[0];
return Math.max.apply( Math, arguments );
}
var min = smallest(10, 11, 12, 13);
var max = largest([10, 11, 12, 13]);
console.log("Smallest: "+ min +", Largest: "+ max);
I think I have an easy-to-understand solution for this, using only the basics of javaScript.
function myFunction() {
var i = 0;
var smallestNumber = justPrices[0];
for(i = 0; i < justPrices.length; i++) {
if(justPrices[i] < smallestNumber) {
smallestNumber = justPrices[i];
}
}
return smallestNumber;
}
The variable smallestNumber is set to the first element of justPrices, and the for loop loops through the array (I'm just assuming that you know how a for loop works; if not, look it up). If an element of the array is smaller than the current smallestNumber (which at first is the first element), it will replace it's value. When the whole array has gone through the loop, smallestNumber will contain the smallest number in the array.
Here’s a variant of Darin Dimitrov’s answer that doesn’t modify the Array prototype:
const applyToArray = (func, array) => func.apply(Math, array)
applyToArray(Math.min, [1,2,3,4]) // 1
applyToArray(Math.max, [1,2,3,4]) // 4
function tinyFriends() {
let myFriends = ["Mukit", "Ali", "Umor", "sabbir"]
let smallestFridend = myFriends[0];
for (i = 0; i < myFriends.length; i++) {
if (myFriends[i] < smallestFridend) {
smallestFridend = myFriends[i];
}
}
return smallestFridend
}
A super-easy way to find the smallest value would be
Array.prototype.min = function(){
return Math.min.apply(Math,this);
};
To call the function, just use the name of the array and add .min()
Array.prototype.min = function(){
return Math.min.apply(Math,this);
};
var arr = [12,56,126,-1,5,15];
console.log( arr.min() );
If you are using Underscore or Lodash you can get the minimal value using this kind of simple functional pipeline
_.chain([7, 6, -1, 3, 2]).sortBy().first().value()
// -1
You also have the .min function
_.min([7, 6, -1, 3, 2])
// -1
Here is code that will detect the lowest value in an array of numbers.
//function for finding smallest value in an array
function arrayMin(array){
var min = array[0];
for(var i = 0; i < array.length; i++){
if(min < array[i]){
min = min;
}else if (min > array[i]){
min = array[i + 1];
}else if (min == array[i]){
min = min;
}
}
return min;
};
call it in this way:
var fooArray = [1,10,5,2];
var foo = arrayMin(fooArray);
(Just change the second else if result from: min = min to min = array[i]
if you want numbers which reach the smallest value to replace the original number.)
Here is a recursive way on how to do it using ternary operators both for the recursion and decision whether you came across a min number or not.
const findMin = (arr, min, i) => arr.length === i ? min :
findMin(arr, min = arr[i] < min ? arr[i] : min, ++i)
Code snippet:
const findMin = (arr, min, i) => arr.length === i ? min :
findMin(arr, min = arr[i] < min ? arr[i] : min, ++i)
const arr = [5, 34, 2, 1, 6, 7, 9, 3];
const min = findMin(arr, arr[0], 0)
console.log(min);
You can use min method in Math object!
const abc = [50, 35, -25, -6, 91];
function findMin(args) {
return Math.min(...args);
}
console.log(findMin(abc));
For anyone out there who needs this I just have a feeling.
(Get the smallest number with multi values in the array)
Thanks to Akexis answer.
if you have let's say an array of
Distance and ID and ETA in minutes
So you do push maybe in for loop or something
Distances.push([1.3, 1, 2]); // Array inside an array.
And then when It finishes, do a sort
Distances.sort();
So this will sort upon the first thing which is Distance here.
Now we have the closest or the least is the first you can do
Distances[0] // The closest distance or the smallest number of distance. (array).