Related
I am trying to add the values of multiple arrays at each index.
Eg.
arr1 = [100, 110, 121]
arr2 = [20, 25, 27.5]
newArr = [120, 135, 148.5]
My current approach is below.
I am finding the percentage change between stocks each day (Day 1, Day 2, Day 3 etc)
Then I am moving to the next stock and I want to add the percentage change of stock 1 and stock 2 together. ie Append the new percentage change to the old percentage change.
What I am trying to do know is check if the index exists as a key in the object, and if it does, add the diff figure to this index.
If the index doesn't exist I want to just add the diff figure.
It is working when the index doesn't exist but when the index does exist (ie. The second, third stock etc) the old value for that index is just overwritten with the newer value.
I want to add them together.
Is there a simple clean solution for this?
accumPercent = {}
const portfolio = props.test.map((item) => {
let oldPrice = item.res.data.o[0]
item.res.data.o.map((item1, index) => {
let diff = ((item.res.data.c[index] - oldPrice) / oldPrice) * 100
oldPrice = item.res.data.c[index]
if (index in Object.keys(accumPercent)) {
accumPercent[index] = accumPercent[index] + diff
} else {
accumPercent[index] = diff
}
})
})
let example = [
{
o: [10, 20, 30]
},
{
o: [10, 40, 60]
}
]
You can use map like this:
const arr1 = [100, 110, 121]
const arr2 = [20, 25, 27.5]
const newArr = arr1.map((i, idx) => i + arr2[idx])
// result: [120, 135, 148.5]
Or if the arrays are in an object:
const test = {arr1: [100, 110, 121], arr2: [20, 25, 27.5]}
const newArr = test.arr1.map((i, idx) => i + test.arr2[idx])
// result: [120, 135, 148.5]
One more way :
let fr = []
arr1.forEach((d,index)=>{
fr.push(d + arr2[index])
})
console.log(fr)
I think the example is the simplest.
I have this array : [10, 30, 55, 75, 94, 112] and the value 69.
I want to get: [55, 75, 94, 112]
So I want to filter out the smaller values but keep the closest.
an idea?
Something like this using filter.
var arr = [1, 3, 5, 7, 9, 11];
var value = 6;
function remove(arr, value) {
let copy = arr;
let newArr = arr.filter((arr, index) => !((arr < value) && (copy[index + 1] < value)))
console.log(newArr)
}
remove(arr, value) // [5, 7, 9, 11]
Just filter, and check if either this or the next value in the array is >= limit
const filter=(array, limit)=>array.filter((value,index)=>value>=limit||array[index+1]>limit);
console.log(filter([10, 30, 55, 75, 94, 112], 69));
Use Array.filter, Array.pop, Array.sort Array.concat
function f(val, array){
// array.sort( (a,b)=>a-b ); // if array isn't sorted, you must be use
return array.filter(e=>e>val).concat([array.filter(e=>e<val).pop()])
}
Given an input array arr and a value val:
Iterate over arr, splicing all elements greater than val into a separate array.
Append the maximum element left in arr to the new array.
arr = [1, 3, 5, 7, 9, 11];
val = 6;
new_arr = []; // Initialize new array
for (let i=0; i<arr.length; i++) { // Iterate over current array
if (arr[i]>val) { // If the current element is greater than the given value
new_arr.push(arr.splice(i, 1)[0]) // Splice it into the new array
i--; // Decrement i so as to not skip any elements
}
}
new_arr.unshift(Math.max(...arr)) // Add the closest value to the new array
console.log(new_arr);
Start by finding the closest delta for numbers that are under the limit. Then filter all numbers that are under the limit, and the their delta with the limit is not equal to the delta you've found in the previous step.
Note: this assumes that the numbers are unique, but they don't have to be sorted.
const fn = (arr, lim) => {
const closestSmallerDelta = arr.reduce((acc, n) =>
lim < n || lim - n > acc ? acc : lim - n
, Infinity)
return arr.filter(n => lim < n || lim - n === closestSmallerDelta)
}
console.log(fn([10, 30, 55, 75, 94, 112], 69));
// unsorted array
console.log(fn([112, 55, 75, 94, 10, 30], 69));
assuming the array is always sorted:
const deleteSmallerButLastOne = (array , refNum ) =>{
const finalArr = []
for(let [index, num] of array.entries()){
if(num < refNum && array[index + 1] >= refNum) finalArr.push(num)
if(num > refNum) finalArr.push(num)
}
return finalArr
}
I took this approach instead of modifying the original array just in case you need it for later.
Here's one possible approach (apparently assuming array is sorted). The idea is to find the very first item that is greater than or equal to lim; when you found it, there's no need to check the rest of an array (and that's what all the other answers do).
function processSorted(arr, lim) {
const i = arr.findIndex(el => el >= lim);
if (i === -1) // no elements greater than lim, return just the last one
return arr.slice(-1);
if (i === 0) // the first element is greater than lim, give back 'em all!
return arr;
return arr.slice(i - 1);
}
console.log(processSorted([10, 30, 55, 75, 94, 112], 69));
It's not sorted, it's possible to sort it anyway, or, if you really strive for n-only, go with one-iteration only approach:
function processUnsorted(arr, lim) {
const res = [];
let oneLess = -Infinity,
len = arr.length;
arr.forEach(el => {
if (el >= lim) res.push(el);
else oneLess = Math.max(oneLess, el);
});
if (oneLess !== -Infinity) res.unshift(oneLess);
return res;
}
console.log(processUnsorted([30, 55, 10, 94, 75, 112], 69));
I have a array like so:
var arr = [[12,45,75], [54,45,2],[23,54,75,2]];
I want to find out the largest element and the smallest element out of all the elements in the nested array:
The min should be: 2
and
Max should be 75
I tried the functions below but they do not work:
function Max(arrs)
{
if (!arrs || !arrs.length) return undefined;
let max = Math.max.apply(window, arrs[0]), m,
f = function(v){ return !isNaN(v); };
for (let i = 1, l = arrs.length; i<l; i++) {
if ((m = Math.max.apply(window, arrs[i].filter(f)))>max) max=m;
}
return max;
}
function Min(arrs)
{
if (!arrs || !arrs.length) return undefined;
let min = Math.min.apply(window, arrs[0]), m,
f = function(v){ return !isNaN(v); };
for (let i = 1, l = arrs.length; i<l; i++) {
if ((m = Math.min.apply(window, arrs[i].filter(f)))>min) min=m;
}
return min;
}
It gives out Max as 75 and min as 12.
Any guidance will be appreciated.
Also tried other answers in SO but none help.
The answer at Merge/flatten an array of arrays in JavaScript? resolves the problem of merging arrays.
Whereas my problem is to keep the array as is and perform operations.
Assuming ES6
const arr = [[12,45,75], [54,45,2],[23,54,75,2]];
const max = Math.max(...[].concat(...arr));
const min = Math.min(...[].concat(...arr));
console.log(max);
console.log(min);
You can flatten the array first (advantage - will work for nested arrays at multiple levels)
var flattenedArr = [[12,45,75], [54,45,2],[23,54,75,2] ].toString().split(",").map(Number);
Then get the min and max from the flattened array
var max = Math.max.apply( null, flattenedArr );
var min = Math.min.apply( null, flattenedArr );
Demo
var flattenedArr = [
[12, 45, 75],
[54, 45, 2],
[23, 54, 75, 2]
].toString().split(",").map(Number);
var max = Math.max.apply(null, flattenedArr);
var min = Math.min.apply(null, flattenedArr);
console.log(max, min);
A ES5 recursive approach by checking the type. It works for deep nested arrays.
var array = [[12, 45, 75], [54, 45, 2], [23, 54, 75, 2]],
min = array.reduce(function min(a, b) {
return Math.min(Array.isArray(a) ? a.reduce(min) : a, Array.isArray(b) ? b.reduce(min) : b);
}),
max = array.reduce(function max(a, b) {
return Math.max(Array.isArray(a) ? a.reduce(max) : a, Array.isArray(b) ? b.reduce(max) : b);
});
console.log(min, max);
With functions for using as callback.
function flat(f, v) { return Array.isArray(v) ? v.reduce(f) : v; }
function getMin(a, b) { return Math.min(flat(getMin, a), flat(getMin, b)); }
function getMax(a, b) { return Math.max(flat(getMax, a), flat(getMax, b)); }
var array = [[12, 45, 75], [54, 45, 2], [23, 54, 75, 2]],
min = array.reduce(getMin),
max = array.reduce(getMax);
console.log(min, max);
You can simply merged all the nested array into a single array and then find minimum and maximum value by using Math.min.apply(null, array) and Math.max.apply(null, array)
var arr = [[12,45,75], [54,45,2],[23,54,75,2]];
var merged = [].concat.apply([], arr);
var max = Math.max.apply(null, merged);
var min = Math.min.apply(null, merged);
console.log(max,min)
Solution without concatenation, which works for any level of nesting
let arr = [[12,45,75], [54,45,2],[23,54,75,2]];
function findMaxFromNestedArray(arr) {
let max = Number.MIN_SAFE_INTEGER;
for (let item of arr) {
if(Array.isArray(item)) {
let maxInChildArray = findMaxFromNestedArray(item);
if (maxInChildArray > max) {
max = maxInChildArray;
}
} else {
if (item > max) {
max = item;
}
}
}
return max;
}
console.log(findMaxFromNestedArray(arr))
Solution with only one reduce:
const getMaxMin = (flattened) => {
return flattened.reduce(
(a, b) => {
return {
maxVal: Math.max(b, a.maxVal),
minVal: Math.min(b, a.minVal),
};
},
{
maxVal: -Infinity,
minVal: Infinity,
}
);
}
const flatSingle = arr => [].concat(...arr)
const maxMin = getMaxMin(flatSingle(arr))
console.log(maxMin);
We can flatten the array with Array.prototype.flat.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
const nestedArray = [[12,45,75], [54,45,2],[23,54,75,2]]
const flattenedArray = nestedArray.flat(2)
const minValue = Math.min.apply(null, flattenedArray)
const maxValue = Math.max.apply(null, flattenedArray)
console.log( {flattenedArray, minValue, maxValue} )
const getFlatArr = (arr) => arr.join().split(',').map(Number)
const getMax = (arr) => {
const newArr = getFlatArr(arr)
let max = newArr[0]
newArr.forEach((value) => {
max = value > max ? value : max
})
return max
}
const getMin = (arr) => {
const newArr = getFlatArr(arr)
let min = newArr[0]
newArr.forEach((value) => {
min = value < min ? value : min
})
return min
}
const arr1 = [
[12, 45, 75],
[54, 45, 2],
[23, 54, 75, 2],
]
console.log(`Max: ${getMax(arr1)}`)
console.log(`Min: ${getMin(arr1)}`)
const arr2 = [1, 2, [14, 56, 34, [48, 98]], [14, 16, 11, [18, 81]], 34, 35]
console.log(`Max: ${getMax(arr2)}`)
console.log(`Min: ${getMin(arr2)}`)
I'm just gonna update this with 3 simple approaches:
Assume you have a nested array:
let numbers = [12, 44, [33, 94, 10444], 104]
Your first step is to flatten the array. There are many ways to do this, but specifically 2 of the most simple ways:
const flat = numbers.flat() // 12, 44, 33, 94, 10444, 104
const flat = [].concat(...numbers) // 12, 44, 33, 94, 10444, 104
Then comes the easy part - determining the min/max of the flattened array:
const min = Math.min(...flat) // 12
const max = Math.max(...flat) // 10444
Alternatively, you can sort the flattened array and get the first and last elements:
flat.sort((a,b) => {return a-b}) // 12, 33, 44, 94, 104, 10444
const min = flat.shift() // 12
const max = flat.pop() // 104444
Say I have an array as follows (each small array is [x, y]):
var myPoints = [[25, 28], [26, 26], [70, 40], [50, 50], [300, 300], [285, 350], [1000, 1000]];
Let's say I need to thin the array down to 4 points. (this is a small example, my acutal array has thousands of points) How could I go about thinning the array based on density so more points are removed from areas with points closer together and less points are removed from areas with lower density?
In this case (reducing the above array from 8 to 4 items) I would expect the returned array to look something like the following:
var thinnedPoints = [[25, 28], [70, 40], [300, 300], [1000, 1000]];
My idea on how to approach this would be to generate a dictionary that maps the point to it's minimum distance to another point (e.g. a point close to another point would have a small minimum distance) then sort the dictionary based on ascending minimum distance, then remove every n'tn item of the dictionary.
The problem with this approach is I don't know how to efficiently generate the distance to closest other point value for each point.
Is there an efficient way to generate those values or maybe is there another way to approach this density based thinning problem?
Thanks!
It seems you want to solve either a P-center problem or a P-median problem.
From Approximability Results for the p-Center Problem by Stefan Buettcher,
The p-Center problem, also known as the Min-Max Multicenter problem
or the Facility Location problem, is a famous problem from operations
research. Informally, it is the problem of placing fire stations in a
city so that the maximum time to reach any point in the city is
minimized.
From Methods for Solving the p-Median Problem: An Annotated Bibliography by J. Reese,
The p-median problem is simply stated as: Given a graph or a network
G = (V, E), find Vp ⊆ V such that |Vp| = p, where p may either
be variable or fixed [...], and that the sum of the shortest distances
from the vertices in {V\Vp} to their nearest vertex in Vp is
minimized.
Both problems are NP-complete in general, so there is no (known) way to solve them in polynomial time. But there are various heuristics you could try.
A very simple and efficent solution that works especially well on large sets is to just pick the points randomly. This implicitly removes less points from regions containing less points than elsewhere - which seems to be just what you want, if you only want to scale the density linearly. It should yield the same results as your approach, without needing to calculate any distances.
If the data is not ordered in any way (i.e. already random), you can also drop every second point or just the first or second half.
If you want to tweak the density distribution non-linearly, you could divide the set into multiple regions (e.g. squares) small enough so that the density is roughly uniform in each of them, and then drop every n-th of the points per region. If you choose the region size appropriately, this approach might also deliver better (and more consisten) results than the purely random one on smaller data sets.
You can use for..of loop, for loop, .map(), Math.min(), .filter().
Loop through each element of array, assign x, y to separate array variables; subtract the difference between each element in x or y arrays; map original array, begin by removing first or second element of matched pair where the two elements have the least numeric difference between any other number in array; that is, the two numbers are separated by the least amount of digits. Continue removing elements, as distance between numbers increases, until n, here, 3, elements are removed from original array.
For example, mapping x can return either
[[25, 28], [70, 40], [300, 300], [1000, 1000]];
or
[[26,26], [50,50], [285,350], [1000,1000]]
as the range between the numbers is the same each in direction
[1, 1, 20, 20, 15, 15, 700]
var myPoints = [
[25, 28],
[26, 26],
[70, 40],
[50, 50],
[300, 300],
[285, 350],
[1000, 1000]
];
var [x, y] = [
[],
[]
];
var [xx, yy] = [
[],
[]
];
for (let z of myPoints) {
[x, y] = [
[...x, z[0]],
[...y, z[1]]
];
}
var stop = 3;
for (var i = 0; i < x.length; i++) {
var prop = x[i];
if (typeof xx[i] !== "object") {
xx[i] = {
index: i,
diff: [],
value: prop
};
}
for (var len = 0; len < x.length; len++) {
var key = x[len];
xx[i].diff.push(
prop > key
? prop - key
: key > prop ? key - prop : Infinity
)
}
}
var range = xx.map(prop => Math.min.apply(Math, prop.diff));
var temp = range.slice(0);
for (var i = 0; i < stop; i++) {
var curr = Math.min.apply(Math, temp);
var index = temp.indexOf(curr);
temp[index] = Infinity;
var pair = Math.min.apply(Math, temp);
var next = temp.indexOf(pair);
temp[next] = Infinity;
x[next] = void 0;
};
var res = myPoints.map((prop, index) =>
x[index] === undefined ? null : prop).filter(Boolean);
console.log(res);
usage as a function
var myPoints = [
[25, 28],
[26, 26],
[70, 40],
[50, 50],
[300, 300],
[285, 350],
[1000, 1000]
];
var filter = (arr, xy, n) => {
var [x, y] = [
[],
[]
];
var [xx, yy] = [
[],
[]
];
for (let z of arr) {
[x, y] = [
[...x, z[0]],
[...y, z[1]]
];
}
var XY = {
"x": [x, xx],
"y": [y, yy]
};
var item = XY[xy];
var stop = n;
for (var i = 0; i < item[0].length; i++) {
var prop = item[0][i];
if (!item[1][i]) {
item[1][i] = {
index: i,
diff: [],
value: prop
};
}
for (var len = 0; len < item[0].length; len++) {
var key = item[0][len];
item[1][i].diff.push(
prop > key ? prop - key : key > prop ? key - prop : Infinity
)
}
}
var range = item[1].map(prop => Math.min.apply(Math, prop.diff));
var temp = range.slice(0);
for (var i = 0; i < stop; i++) {
var curr = Math.min.apply(Math, temp);
var index = temp.indexOf(curr);
temp[index] = Infinity;
var pair = Math.min.apply(Math, temp);
var next = temp.indexOf(pair);
temp[next] = Infinity;
item[0][next] = void 0;
};
return arr.map((prop, index) =>
item[0][index] === undefined ? null : prop).filter(Boolean);
}
console.log(filter(myPoints, "x", 3));
I have a list of numbers (any length) ranging from 0 - 100, including duplicates. I need convert those numbers to portions of 100.
For example:
[25, 50] becomes [33.333, 66.666]
[25, 50, 50] becomes [20, 40, 40]
What algorithm would work best for this?
You would need to calculate the sum of the values in your array - then you could divide each value in your array by that sum, and multiply by 100.
Try this :
console.log(33.333 - 33.333 % 25); // 50
% is MODULO operator.
Number.prototype.range = function(a) {
return this - this % a;
}
console.log((33.333).range(25)); // 25;
console.log((66.666).range(25)); // 50;
In array use map like this :
console.log([33.333, 66.666].map(function(a) {
return a.range(25);
}));
Demo
This can be done by calculating the sum of the array and then dividing each value by that. It can be done easily using Array.reduce to sum and Array.map to create a new array with the final output. Here is an example:
var arr1 = [25, 50];
var arr2 = [25, 50, 50];
function proportion(arr) {
var sum = arr.reduce(function(prev, cur){
return prev + cur;
});
var result = arr.map(function(val){
return (val/sum)*100;
});
return result;
}
console.log(proportion(arr1)); // [33.33333333333333, 66.66666666666666]
console.log(proportion(arr2)); // [20, 40, 40]
JSBin here: http://jsbin.com/texuc/1/edit
The simplest way to solve this is to sum the array, find each value as a fraction of that sum, and then multiply by 100.
This code should do the trick.
var inputArray = [25, 50, 50];
var outputArray = [];
var total = 0;
for (var i=0; i<(inputArray.length); i++) {
total += inputArray[i];
}
for (var i=0; i<(inputArray.length); i++) {
outputArray[i] = ((inputArray[i])/total) * 100;
}