get closest number out of array in array in javascript - javascript

I know this is a bit on nonsense but I need to get the closest number out of 2 arrays or:
const myarr = [[12, 42], [12, 56], [30, 54]]
console.log(colsest_out_of_closest(myarr, [12, 50]))

It looks like you want to find the smallest difference between both the min and the max.
const closest_out_of_closest = (arr, criteria) => {
const [min, max] = criteria;
let result, prevDiff = Number.MAX_VALUE;
arr.forEach((item) => {
const [localMin, localMax] = item;
const diff = Math.abs(localMin - min) + Math.abs(localMax - max);
if (diff < prevDiff) {
prevDiff = diff;
result = item;
}
});
return result;
};
const myarr = [[12, 42], [12, 56], [30, 54]];
console.log(closest_out_of_closest(myarr, [12, 50])); // [12, 56]
Here is a reducer version that is less bytes, but still readable:
const closestRange = (arr, [min, max]) =>
arr.reduce((acc, [lMin, lMax]) =>
(diff => diff < acc.prev ? { result: [lMin, lMax], prev: diff } : acc)
(Math.abs(lMin - min) + Math.abs(lMax - max)),
{ result: null, prev: Number.MAX_VALUE }).result;
console.log(closestRange([[12, 42], [12, 56], [30, 54]], [12, 50])); // [12, 56]

You could check the absolute delta.
const
getClosest = (a, b, t) => Math.abs(t - a) < Math.abs(t - b) ? a : b,
getClosestPair = (target, array) => values.reduce((a, b) =>
[0, 1].map(i => getClosest(a[i], b[i], target[i]))
),
values = [[12, 42], [12, 56], [30, 54]],
closest = getClosestPair([12, 50], values);
console.log(closest);

Related

How to remove '-' from the array number elements run through this function in JS?

I'm using this function below to sum "columns" of a 2D Array, but some elements contain '-' and I haven't been able to handle it:
I've tried Number(num) or typeof num === 'number', but still...
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const sumArray = (array) => {
const newArray = [];
array.forEach(sub => {
sub.forEach((num, index) => {
if(newArray[index]){
newArray[index] += num;
}else{
newArray[index] = num;
}
});
});
return newArray;
}
console.log(sumArray(arr))
You could use map and reduce to achieve this as well.
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1],
];
const sums = arr.map((sub) =>
sub.reduce((previous, current) => {
// check here that the value is a number
if (typeof current === 'number') {
return previous + current;
}
return previous;
}, 0)
);
console.log(sums);
// returns [23, 59, 9, 20]
Try:
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const sumArray = (array) => {
const newArray = [];
array.forEach(sub => {
sub.forEach((num, index) => {
if (typeof num == 'number') {
if (newArray[index]) {
newArray[index] += num;
} else {
newArray[index] = num;
}
}
});
});
return newArray;
}
console.log(sumArray(arr))
Here's a more concise solution:
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const result = arr.map((e, i) => arr.reduce((a, c) => (typeof c[i] == 'number' ? a + c[i] : a), 0))
console.log(result)
Using splice() would help remove the - from the array

How can i improve this Javascript code that arrange the array in ordered list first and put them in an array of array with same value?

Can this code be Improved? It arrange our array into sorted list(sortedArray) first and, the finalArray takes the final result;Example finalArray = [[1,1,1,1][2,2,2]...]
let array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20]
let sortedArray = []
let finalArray = []
sortedArray = array.sort((a, b) => {
if (a > b) return 1;
if (a < b) return -1;
return sortedArray.push(a - b);
});
finalArray = sortedArray.reduce((item, index) => {
if (typeof item.last === 'undefined' || item.last !== index) {
item.last = index;
item.sortedArray.push([]);
}
item.sortedArray[item.sortedArray.length - 1].push(index);
return item;
}, {
sortedArray: []
}).sortedArray;
console.log(finalArray);
Here is a shorter version than yours and more readable than Nina's
let array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20]
const finalArray = array.slice(0) // copy the array
.reduce((acc,cur) => {
const idx = acc.findIndex(item => item[0] === cur);
if (idx !=-1) acc[idx].push(cur); // just push
else acc.push([cur]); // push as array
return acc
},[])
.sort(([a],[b]) => a-b); // sort on the first entry
console.log(finalArray);
You could group first and then sort by the first item of each array.
If you have only positive 32 bit intger values, you could omit sorting, because the object is sorted like an array.
const
array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20],
result = Object
.values(array.reduce((r, v) => {
(r[v] ??= []).push(v);
return r;
}, {}))
.sort(([a], [b]) => a - b);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

how to sort array by last digit?

I am required to write a function that receives an array of numbers and
should return the array sorted using for the comparison of their last digit, if their last digit is the same you should check the second to last and so on.
Example:
Input: [1, 10, 20, 33, 13, 60, 92, 100, 21]
Output: [100, 10, 20, 60, 1, 21, 92, 13, 33]
but I get
Output: [ 10, 20, 60, 100, 1, 21, 92, 33, 13 ]
my code:
/**I guess the input numbers are only integers*/
input = [1, 10, 20, 33, 13, 60, 92, 100, 21];
const reverseString = (string) => {
const stringToArray = string.split("");
const reversedArray = stringToArray.reverse();
const reversedString = reversedArray.join("");
return reversedString;
};
let sortedInput = input.sort((firstNumber, secondNumber) => {
const firstNumberReversed = reverseString(firstNumber.toString());
const secondNumberReversed = reverseString(secondNumber.toString());
const largerOne = Math.max(
firstNumberReversed,
secondNumberReversed
).toString;
for (let i = 0; i < largerOne.length; i++) {
if (firstNumberReversed[i] != secondNumberReversed[i]) {
if(firstNumberReversed[i] > secondNumberReversed[i]){
return 1
}
if(secondNumberReversed[i] > firstNumberReversed[i]){
return -1
}
}
}
});
console.log(sortedInput);
You can achieve this result if you sort it after reversing the number
const arr = [1, 10, 20, 33, 13, 60, 92, 100, 21];
const result = arr
.map((n) => [n, n.toString().split("").reverse().join("")])
.sort((a, b) => a[1].localeCompare(b[1]))
.map((a) => a[0]);
console.log(result);
You can do this using the Remainder Operator:
Demo:
const data = [1, 10, 20, 33, 13, 60, 92, 100, 21];
data.sort((a, b) => {
for (let i = 1, sum = a + b; ; i *= 10) {
const diff = (a % i) - (b % i);
if (diff === 0 && i < sum) continue;
return diff;
}
});
console.log(data);

Find duplicates of an array and replace it with its number

Say I have an array:
arr = [25, 25, 25, 20, 15, 10, 10, 5];
and I want to count up the number of duplicates (ie. three 25s and 2 10s) and make a new array that becomes:
newArr = ['25 * 3', 20, 15, '10 * 2', 5];
How should I go about doing this? Thanks!
It can be solved using Set and filter
let arr = [25, 25, 25, 20, 15, 10, 10, 5];
const newArr = [...new Set(arr)].map((x) => {
const count = arr.filter(y => y == x).length
return count > 1 ? x + " * " + count: x;
})
console.log(newArr) //  ["25 * 3", 20, 15, "10 * 2", 5]
or if you want the numeric value you can do that
let arr = [25, 25, 25, 20, 15, 10, 10, 5];
const newArr = [...new Set(arr)].map((x) => arr.filter(y => y == x).length * x)
console.log(newArr) // [75, 20, 15, 20, 5]
You can use a Array#forEach loop to iterate through each item of the array, keeping track of how many times each item has been seen before.
Demo:
let arr = [25, 25, 25, 20, 15, 10, 10, 5];
let result = [], seenBefore = [];
arr.forEach((item) => {
let seen = seenBefore.indexOf(item);
if (seen !== -1) return result[seen].count++;
result.push({ name: item, count: 1 });
seenBefore.push(item);
});
result = result.map(({ name, count }) =>
count > 1 ? `${name} * ${count}` : name
);
console.log(result);
The same technique but smaller using Array#reduce:
let arr = [25, 25, 25, 20, 15, 10, 10, 5];
let result = arr
.reduce(
(acc, item) => {
acc[1].indexOf(item) !== -1 ? acc[0][acc[1].indexOf(item)].count++ : (acc[0].push({ name: item, count: 1 }), acc[1].push(item));
return acc;
},
[[], []]
)[0]
.map(({ name, count }) => (count > 1 ? `${name} * ${count}` : name));
console.log(result);
You could use reduce and check if the current element in the iteration is equal to the previous element and then also what is the type of last element added to the accumulator.
const arr = [25, 25, 25, 20, 15, 10, 10, 5];
const result = arr.reduce((r, e, i, arr) => {
if (i && e === arr[i - 1]) {
if (typeof r[r.length - 1] === 'number') {
r[r.length - 1] = `${e} * 2`;
} else {
const [key, value] = r[r.length - 1].split(' * ')
r[r.length - 1] = `${key} * ${+value + 1}`
}
} else {
r.push(e)
}
return r;
}, [])
console.log(result)

Deduplicate array of arrays whilst transforming items at the same time

I have an array like this:
[
["01/07", 1, 13],
["02/07", 0, 16],
["03/07", 0, 5],
["01/07", 2, 0],
["02/07", 2, 0],
["03/07", 12, 0],
["04/07", 12, 0],
["05/07", 9, 0]
]
I would like to join the rows when there are 2 equal dates and sum the 2 numeric values,
using the example above the result would be:
[
["01/07", 3, 13],
["02/07", 2, 16],
["03/07", 12, 5],
["04/07", 12, 0],
["05/07", 9, 0]
]
What would be the best possible way to achieve this?
Here is a solution using .reduce:
const joined = data.reduce((joined, [date, a, b]) => {
const match = joined.find(([dateB]) => dateB == date);
match ? (match[1] += a) && (match[2] += b) : joined.push([date, a, b]);
return joined;
}, []);
Here's a live example:
'use strict';
const data = [
["01/07", 1, 13],
["02/07", 0, 16],
["03/07", 0, 5],
["01/07", 2, 0],
["02/07", 2, 0],
["03/07", 12, 0],
["04/07", 12, 0],
["05/07", 9, 0]
];
const joined = data.reduce((joined, [date, a, b]) => {
const match = joined.find(([dateB]) => dateB == date);
match ? (match[1] += a) && (match[2] += b) : joined.push([date, a, b]);
return joined;
}, []);
console.log(joined);
const collaspsedArray = jsArray.reduce((acc, el) => {
const index = acc.findIndex(x => x[0] === el[0])
if (index === -1) {
acc.push(el)
return acc
}
for (let i = 1; i < acc[index].length; i++) {
acc[index][i] += el[i]
}
return acc
}, [])
I like this way
Use Array#reduce and a map to group entries by date. When adding to the map sum the numbers, then export the values with Object.values:
const unique_sum = xs =>
Object.values(
xs.reduce((acc, [date, a, b]) => {
const [, aa=0, bb=0] = acc[date] || [];
acc[date] = [date, a + aa, b + bb];
return acc;
}, {}));
console.log(unique_sum(data));
<script>
const data = [
["01/07", 1, 13],
["02/07", 0, 16],
["03/07", 0, 5],
["01/07", 2, 0],
["02/07", 2, 0],
["03/07", 12, 0],
["04/07", 12, 0],
["05/07", 9, 0]
];
</script>

Categories

Resources