How would i get get min Y value for graph? - javascript

I don't know how to explain this but i will try my best, so sorry in advance
For example this numbers
i would like to get
5 => 1, 12 => 10, 128 => 120, 1493 => 1400, 13301 => 13000
I have came up with Math.pow(10, Math.floor(Math.log10(x)));
which returns me 1, 10, 100, 1000, 10000

You could get the exponent and a factor and check if the value is smaller than 100, then take just the decimal with the exponent or the adjusted value.
function format(v) {
var e = Math.floor(Math.log10(v)),
f = 10 ** (e - 1);
return v < 100
? 10 ** e
: Math.floor(v / f) * f;
}
console.log(...[5, 12, 128, 1493, 13301, 239584].map(format));
// 1, 10, 120, 1400, 13000, 230000

Related

Create array with numbers +10/-10, where middle one is 0, depending on what length I want

I need to dynamically create array, knowing only how long I want it to be. So for example I need array to be 3 long so I need array = [-10, 0, 10], if I need array 9 long it will be [-40, -30, -20, -10, 0, 10, 20, 30, 40] etc. How can I do it automatically?
You can simply get the result using Array with fill
Since you only want 0 at the center that input should be odd.
const end = 9;
let start = Math.floor(end / 2);
const result = [
...Array(start).fill(0).map((_, i) => start * -10 + i * 10),
0,
...Array(start).fill(0).map((_, i) => (i + 1) * 10)
]
console.log(result)
Another solution with Array.from:
const createArray = (length) => Array.from({length}, (el, i) => Math.round(i - length / 2) * 10);
console.log(createArray(1))
console.log(createArray(3))
console.log(createArray(9))

How to determine the fewest number of Y increments needed to plot a multiple of 5 on a graph?

Using JavaScript, an array of numbers is going to be charted on a graph (for my purposes it is a spline chart):
[12, 22, 25, 38, 47]
I want all the Y axis values to be multiples of 5. I have the Y axis capped at the next multiple of 5 that occurs after the highest number in the array. Since 47 is the highest number, the next multiple of 5 is 50 (call that value the "cap"), and that is the top value ("tick") on the chart's Y axis. After figuring that out, I know that the Y axis should be 0 a the bottom, and 50 at the top, but I want to override the default behavior and tell it exactly how many ticks to show in between, and what the values should be for those ticks.
This is where it gets tricky, because of the following restrictions:
Use the fewest number of ticks possible (0, the max value, and at least one tick in between)
Bottom value is always zero
All Y tick values are multiples of 5
Y ticks are evenly spaced on the axis
For the previous example, fifty is the cap, which is divisible by two, so the Y axis would only need one tick in between the bottom and top, resulting in three tick values of 0, 25, 50. The function I am trying to build would receive 50 as an argument, and output 3 as the result. Then I would know the chart needs 3 ticks, and I could generate it like so:
My question is, given that a charted value can be any multiple of 5, how can I calculate the fewest number of ticks needed on the Y axis, using only increments that are multiples of 5? It may be easiest to just show the first few scenarios to illustrate how the pattern is not (at least to me) obvious:
value = tick1, tick2, tick3, etc. >> return count of ticks
05 = 5, 4, 3, 2, 1, 0 >> return 6;// This case is an outlier and can be set manually
10 = 10, 5, 0 >> return 3;
15 = 15, 10, 5, 0 >> return 4;
20 = 20, 10, 0 >> return 3;
25 = 25, 20, 15, 10, 5, 0 >> return 6;
30 = 30, 15, 0 >> return 3;
35 = 35, 30, 25, 20, 15, 10, 5, 0 >> return 8;
40 = 40, 20, 0 >> return 3;
45 = 45, 30, 15, 0 >> return 4;
50 = 50, 25, 0 >> return 3;
55 = 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0 >> return 12;
It was at this point that I realized there is probably an equation or function that exists to address this dilemma, maybe even something to do with the Fibonacci sequence or Dan Brown. I couldn't find any related SO questions, and my use of "increments of 5" may make this use case too specific to return google results on the general principle, so any advice is appreciated.
You could take an iterative approach by using the fifth of the value an checke the abulity for the division by 2, 3, 5, 7 and so on and return this value incremented by one.
const
fn = v => {
v /= 5;
if (v === 1) return 6;
if (v % 2 === 0) return 3;
var i = 1;
while ((i += 2) < v) if (v % i === 0) return i + 1;
return v + 1;
},
format = s => s.toString().padStart(2);
var values = Array.from({ length: 12 }, (_, i) => (i + 1) * 5),
data = values.map(fn);
console.log(...values.map(format));
console.log(...data.map(format));

How to map a number in some ranges

I have a range of values like, for example, [0, 100] = [minValue, maxValue] and the number of bands, for example BANDS_NUMBER = 5.
So I can obtain these bands:
[0 - 20]
[21 - 40]
[41 - 60]
[61 - 80]
[81 - 100]
Then I want to associate a scale value at each range:
i: 0 --> [0 - 20] --> 0.2
i: 1 --> [21 - 40] --> 0.4
i: 2 --> [41 - 60] --> 0.6
i: 3 --> [61 - 80] --> 0.8
i: 4 --> [81 - 100] --> 1
This value is computed in this way: (i + 1) / BANDS_NUMBER where i is the index of a hypothetical loop.
Then I have an input n whose value is in range [minValue, maxValue] = [0, 100].
What I want is the scale value related to this number.
So, for example, if:
n = 0 --> scaleValue = 0.2
n = 10 --> scaleValue = 0.2
n = 20 --> scaleValue = 0.2
n = 35 --> scaleValue = 0.4
n = 68 --> scaleValue = 0.8
n = 99 --> scaleValue = 1
...
How can I create a function like that? I imagine a function like that:
function map(n, minValue, maxValue, bandsNumber) {
const scaleValue = ...
return scaleValue
}
All the values here are examples, I want that all works with any other values.
I don't know how to do to that. I need some help...
Nina Scholz's answer is wrong. Her normalize function returns 0.4 instead of 0.2 for the value 20:
function normalize(min, max, bands, n) {
return n === max
? 1
: Math.floor(1 + ((n - min) / (max - min)) * bands) / bands;
}
console.log(normalize(0, 100, 5, 20)); // expected 0.2, actual 0.4
Because 20 is in the first band, it should have the value 0.2:
i: 0 --> [0 - 20] --> 0.2
i: 1 --> [21 - 40] --> 0.4
i: 2 --> [41 - 60] --> 0.6
i: 3 --> [61 - 80] --> 0.8
i: 4 --> [81 - 100] --> 1
The correct answer is:
const index = (min, max, bands, n) =>
Math.floor(bands * (n - min) / (max - min + 1));
const band = n => index(0, 100, 5, n);
console.log(band(0), band(20)); // 0 0
console.log(band(21), band(40)); // 1 1
console.log(band(41), band(60)); // 2 2
console.log(band(61), band(80)); // 3 3
console.log(band(81), band(100)); // 4 4
As you can see, the edge cases are handled correctly. How did we get to this answer?
First, we find the length of the range which is max - min + 1. The + 1 is important because there are 101 elements in the range [0 - 100] inclusive.
Next, we get the index of the number n in the given range (i.e. n - min).
Then, we divide the index of n by the number of elements in the range to get a value in the range [0 - 1). Note that 1 is not in the range.
Finally, we multiply this value by the number of bands and discard the fractional part. The result is our index.
Note that if the length of the range is not divisible by the number of bands then the first x bands will have one additional element, where x is the remainder of dividing the length of the range by the number of bands.
Finally, we can get the value you want by incrementing the resulting index and then dividing it by the number of bands:
const index = (min, max, bands, n) =>
Math.floor(bands * (n - min) / (max - min + 1));
const value = (min, max, bands, n) =>
(index(min, max, bands, n) + 1) / bands;
const result = n => value(0, 100, 5, n);
console.log(result(0), result(20)); // 0.2 0.2
console.log(result(21), result(40)); // 0.4 0.4
console.log(result(41), result(60)); // 0.6 0.6
console.log(result(61), result(80)); // 0.8 0.8
console.log(result(81), result(100)); // 1 1
Hope that helps.
You could take a formula, which take the range and the slot and returns a normalized value.
Because of the range, which is a bit too long (the last value is included in the interval), you need a check for the last value and prevent getting the next value, outside of the wanted interval.
function normalize(min, max, bands, n) {
return n === max
? 1
: Math.floor(1 + ((n - min) / (max - min)) * bands) / bands;
}
// 0.2 0.2 0.4 0.4 0.8 1 1
console.log(...[0, 10, 20, 35, 68, 99, 100].map(normalize.bind(null, 0, 100, 5)));
You can use a native Array.map function to map each value.
Something like this:
const vals = [
[0, 20],
[21, 40],
[41, 60],
[61, 80],
[81, 100],
];
const BANDS_NUMBER = 5;
const result = vals.map((range, index) => (index + 1) / BANDS_NUMBER);
console.log(result);

How to find nearest pair of number to given pair of number?

I have one array of objects which have pair of numbers and i have one given pair
let points = [{x:20,y:30}, {x:34,y:40}, {x:45,y:30}, {x:55,y:30}]
let givenNumber= {x:19,y:25}
How i can find nearest pair from array which is near to my given pair number
Anyone can help?
You could get the distance and then reduce the array by taking the smaler distance of two points of the array.
const distance = (p1, p2) => Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
let points = [{ x: 20, y: 30 }, { x: 34, y: 40 }, { x: 45, y: 30 }, { x: 55, y: 30 }],
point = { x: 19, y: 25} ,
result = points.reduce((a, b) => distance(a, point) < distance(b, point) ? a : b);
console.log(result);

round number to 3 decimal points (only if necessary)

Instead of Math.round() and toFixed(), what is the alternative way to maintain 3 decimal if only divisible number contain decimal.
I want to have
100 / 30 => 3.333
390 / 100 => 3.90
100 / 100 => 1
You could fix the decimals and replace last zeroes with dot, if necessary.
function round(n) {
return function (v) {
return v.toFixed(n).replace(/\.?0+$/, '');
};
}
var array = [100 / 30, 390 / 100, 100 / 100, 100];
console.log(array.map(round(3)));
With a first keeping zero.
function round(n) {
return function (v) {
return v.toFixed(n).replace(/0+$/, '0').replace(/\.0+$/, '');
};
}
var array = [100 / 30, 390 / 100, 100 / 100, 100];
console.log(array.map(round(3)));

Categories