I have a odd problem that I'm trying to find the most optimal solution for it. So, I'm writting a Node Js function that will print a array on a specific format, like this:
TITLE A
- element 1
- element 3
TITLE B
- element 4
- element 5
TITLE C
- element 2
So, we could have this example array:
[
{title: "TITLE A", text: "element 1"},
{title: "TITLE C", text: "element 2"},
{title: "TITLE B", text: "element 4"},
{title: "TITLE A", text: "element 3"},
{title: "TITLE B", text: "element 5"}
]
The titles can be sorted alphabetically, like this:
details.sort((a, b) => a.title.localeCompare(b.title));
What's the most optimal way to achieve what I want?
Thanks in advance.
CodePudding user response:
EDIT : Hope this one will help you
NOTE : You can groupBy your array by using reduce methode of array
// Array of our element
let array = [
{title: "TITLE A", text: "element 1"},
{title: "TITLE C", text: "element 2"},
{title: "TITLE B", text: "element 4"},
{title: "TITLE A", text: "element 3"},
{title: "TITLE B", text: "element 5"}
]
// Return object grouped by the property as key and value is the incProperty
function groupBy(objectArray, property, incProperty) {
return objectArray.reduce((acc, obj) => {
const key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
// Add object to list for given key's value
acc[key].push(obj[incProperty]);
return acc;
}, {});
}
// We groupBy our array by title and add as value the text
let groupByArray = groupBy(array, 'title', 'text');
// Init of our attempt result
let finalResult = ''
// We Browse our object, at first we concat the key then we browse all values and concat them
// into our result
for (const [key, value] of Object.entries(groupByArray)) {
finalResult = finalResult.concat(key, "\n")
value.forEach(el => {
finalResult =finalResult.concat("- ", el, "\n")
})
}
console.log(finalResult)
CodePudding user response:
Since there is already a working answer here, I will show this one. But please, don't treat StackOverflow as a free coding service. Treat it as a Q & A site, where you're expected to put in real effort into solving the problem before posting, and supposed to demonstrate that effort in the question itself.
Here's a solution built atop a generic groupBy
function that takes a function which converts your elements into strings and returns a function from an array of elements into an object, keyed by those strings, with corresponding values all the elements that yield that string. For instance,
groupBy (x => x % 10) ([21, 15, 11, 3, 5, 1, 7])
//=> {"1": [21, 11, 1], "3": [3], "5": [15, 5], "7": [7]}
We then write format
atop this, first using groupBy
to convert to this structure:
{
"TITLE A": [
{text: "element 1", title: "TITLE A"},
{text: "element 3", title: "TITLE A"}
],
"TITLE B": [
{text: "element 4", title: "TITLE B"},
{text: "element 5", title: "TITLE B"}
],
TITLE C: [
{text: "element 2", title: "TITLE C"}
]
}
then using Object .values
to turn that into an array of key-value pairs, where the keys are the titles, and the values are the arrays of matching elements, then sorting on they keys, then turning these into arrays of strings, with the title followed by all the values, each prepended with -
, and finally joining these together with \n
.
The code looks like this:
const groupBy = (fn) => (xs) =>
xs .reduce ((a, x, _, __, k = fn (x)) => ((a [k] ??= []), (a[k] .push (x)), a), {})
const format = (xs) => Object .entries (groupBy (x => x.title) (xs))
.sort (([a], [b]) => a .localeCompare (b))
.flatMap (([k, vs]) => [k, ...vs .map (v => v .text) .map (s => `- ${s}`)])
.join ('\n')
const input = [{title: "TITLE A", text: "element 1"}, {title: "TITLE C", text: "element 2"}, {title: "TITLE B", text: "element 4"}, {title: "TITLE A", text: "element 3"}, {title: "TITLE B", text: "element 5"}]
console .log (format (input))