Find duplicates of an array and replace it with its number - javascript

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)

Related

get closest number out of array in array in 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);

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 get the number of pair values in array? Javascript

I am trying this solution but it is not giving me the result I want.
I don't want to count the number of pairs of 1 cause it is not really a pair as it appears 4 times.
I need to count the "perfect" pairs, like in this case: 5 and 2. Right now this is giving me 4 as result and it should be 2.
How could I achieve that? I am stuck.
let ar1 = [12, 5, 5, 2, 1, 1, 1, 1, 2];
const countPairs = (ar) => {
let obj = {};
ar.forEach((item) => {
obj[item] = obj[item] ? obj[item] + 1 : 1;
});
return Object.values(obj).reduce((acc, curr) => {
acc += Math.floor(curr / 2);
return acc;
}, 0);
};
console.log( countPairs(ar1) )
You can filter the object values by 2 and count the list
let ar1 = [12, 5, 5, 2, 1, 1, 1, 1, 2];
const countPairs = (ar) => {
let obj = {};
ar.forEach((item) => {
obj[item] = obj[item] ? obj[item] + 1 : 1;
});
return Object.values(obj).filter(e => e == 2).length;
};
console.log(countPairs(ar1))
This can be one-liner using Map as:
const countPairs(arr) => [...arr.reduce((dict, n) => dict.set(n, (dict.get(n) ?? 0) + 1), new Map()).values(),].filter((n) => n === 2).length;
let ar1 = [12, 5, 5, 2, 1, 1, 1, 1, 2];
const countPairs = (arr) =>
[
...arr
.reduce((dict, n) => dict.set(n, (dict.get(n) ?? 0) + 1), new Map())
.values(),
].filter((n) => n === 2).length;
console.log(countPairs(ar1));
or that
const
ar1 = [12, 5, 5, 2, 1, 1, 1, 1, 2]
, countPerfectPairs = arr => arr.reduce((r,val,i,{[i+1]:next})=>
{
if(!r.counts[val])
{
r.counts[val] = arr.filter(x=>x===val).length
if (r.counts[val]===2) r.pairs++
}
return next ? r : r.pairs
},{counts:{},pairs:0})
console.log( countPerfectPairs(ar1) )
If you prefer Details:
const
ar1 = [12, 5, 5, 2, 1, 1, 1, 1, 2]
, countPerfectPairs = arr => arr.reduce((r,val)=>
{
if(!r.counts[val])
{
r.counts[val] = arr.filter(x=>x===val).length
if (r.counts[val]===2) r.pairs++
}
return r
},{counts:{},pairs:0})
console.log( countPerfectPairs(ar1) )

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);

Categories

Resources