Here is the array:
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20]
How can I achieve the following output?
output: // [[1, 1, 1, 1], [2, 2, 2], 4, 5, 10, [20, 20], 391, 392, 591]
Thanks for any help provided!
CodePudding user response:
This should work:
let array = [1, 1, 3, 2, 2, 5, 6, 4, 4];
array.sort((a, b) => a > b);
const result = [];
while(array.length > 0) {
const firstEl = array[0];
array.splice(0,1);
const current = [firstEl];
for(let x = 0; x < array.length; x ) {
if(array[x] == firstEl) {
current.push(array[x]);
array.splice(x, 1);
}
}
result.push(current);
}
console.log(result);
CodePudding user response:
You can use a basic 'group by' and then flatten any arrays in the result with length 1.
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const result = Object.values(arr
.reduce((a, c) => {
(a[c] ??= []).push(c);
return a;
}, {}))
.map(a => a.length > 1 ? a : a[0]);
console.log(result);
The sorting that is seen in the output is a result of of javascript object property ordering which sorts integer keys first in ascending order, followed by non-integer keys in insertion order, see: Does JavaScript guarantee object property order?.
Edit
The same logic as the above can be implemented in a more transparent way using a for
loop with explicit checks for properties instead of using nullish coallescing assignment (??=)
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const grouped = {};
for (const element of arr) {
if (grouped[element] === undefined) {
grouped[element] = [];
}
grouped[element].push(element);
}
const result = Object.values(grouped)
.map(a => a.length > 1 ? a : a[0]);
console.log(result);
CodePudding user response:
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20]
result = [
...arr
.sort((x, y) => x - y)
.reduce(
(m, x) => m.set(x, (m.get(x) ?? 0) 1),
new Map
)
].map(
([x, n]) => n === 1 ? x : Array(n).fill(x))
console.log(...result)
This produces what you're looking for, however that unpacking looks really ugly. How about a small utility function?
Object.prototype.tap = function (fn, ...args) {
return fn(this, ...args)
}
//
result = arr
.sort((x, y) => x - y)
.reduce(
(m, x) => m.set(x, (m.get(x) ?? 0) 1),
new Map
)
.tap(Array.from)
.map(
([x, n]) => n === 1 ? x : Array(n).fill(x))