I have this array
const rows = [
{data: [{text: "A",value: 100}, {text: "B",value: 74}], group: "Elephant"},
{data: [{text: "C",value: 63}, {text: "D",value: 1}], group: "Elephant"},
{data: [{text: "E",value: 37}, {text: "F",value: 54}], group: "Penguin"},
{data: [{text: "G", value: 72}, {text: "H", value: 74}], group: "Lion"},
{data: [{text: "K", value: 76}, {text: "L", value: 38}], group: "Zebra"},
{data: [{text: "M", value: 68}, {text: "N", value: 21}], group: "Lion"},
];
And these sort functions
const _sortFunction = (
a,
b,
columnIndex,
sortOrder
) => {
if (a && a.data && b && b.data) {
if (a.data[columnIndex].value === b.data[columnIndex].value) {
return 0;
} else {
if (sortOrder === "ASC") return a.data[columnIndex].value > b.data[columnIndex].value ? -1 : 1;
if (sortOrder === "DESC") return a.data[columnIndex].value < b.data[columnIndex].value ? -1 : 1;
return 0;
}
} else {
return 0;
}
};
const sortRowsByColumn = (rows, sortProps) => {
if (sortProps && rows) {
const {indexOfColumnToSort, sortOrder} = sortProps;
const rowsCopy = JSON.parse(JSON.stringify(rows))
return rowsCopy.sort((a, b) => _sortFunction(a, b, indexOfColumnToSort, sortOrder));
}
return rows;
};
Which gives me console.log(sortRowsByColumn(rows, {indexOfColumnToSort: 1, sortOrder: "ASC"}))
[
{data: [{text: "A", value: 100}, {text: "B", value: 74}], group: "Elephant"},
{data: [{text: "G", value: 72}, {text: "H", value: 74}], group: "Lion"},
{data: [{text: "E", value: 37}, {text: "F", value: 54}], group: "Penguin"},
{data: [{ text: "K", value: 76}, {text: "L", value: 38}], group: "Zebra"},
{data: [{text: "M", value: 68}, {text: "N", value: 21}], group: "Lion"},
{data: [{text: "C", value: 63}, {text: "D", value: 1}],group: "Elephant"}
]
However, what I cannot get my head around is the following:
The updated sortRowsByColumn()
function should
rows
array based on the group
key (alphabetically)all of this without loosing the original array structure. Basically like a grouping and sorting for each group, without modifiying the array structure or the original array. The result should look like this
[
{data: [{text: "A",value: 100}, {text: "B", value: 74}], group: "Elephant"},
{data: [{text: "C", value: 63}, {text: "D", value: 1}], group: "Elephant"},
{data: [{text: "G", value: 72}, {text: "H", value: 74}], group: "Lion"},
{data: [{text: "M", value: 68}, {text: "N", value: 21}], group: "Lion"},
{data: [{text: "E",value: 37}, {text: "F", value: 54}], group: "Penguin"},
{data: [{text: "K", value: 76}, {text: "L", value: 38}], group: "Zebra"},
]
Achieving this is immediate by using a TrueSet
and an appropriate representation
function.
To arrange your items first by group
and then by data[index].value
, simply represent each item (each row) using such a couple of properties:
[item.group, item.data[index].value]
within a TrueSet
. Nothing else is required.
const
index = 1,
repr = item => [item.group, item.data[index].value],
got = TrueSet.of(repr, ORDER.ASCENDING, ORDER.DESCENDING)
.letAll(data);
Please note that in your _sortFunction()
you are mistakenly referring to ASC
for what is actually a descending order. Therefore, I utilize the ORDER.DESCENDING
comparator for values. However, the groups are sorted using the ORDER.ASCENDING
comparator.
You can check the validity of the proposed solution by:
import { TrueSet } from "@ut8pia/classifier/queue/TrueSet.js";
import { ORDER } from "@ut8pia/classifier/global.js";
import assert from "assert";
const
data = [
{data: [{text: "A",value: 100}, {text: "B",value: 74}], group: "Elephant"},
{data: [{text: "C",value: 63}, {text: "D",value: 1}], group: "Elephant"},
{data: [{text: "E",value: 37}, {text: "F",value: 54}], group: "Penguin"},
{data: [{text: "G", value: 72}, {text: "H", value: 74}], group: "Lion"},
{data: [{text: "K", value: 76}, {text: "L", value: 38}], group: "Zebra"},
{data: [{text: "M", value: 68}, {text: "N", value: 21}], group: "Lion"},
],
expected = [
{data: [{text: "A",value: 100}, {text: "B", value: 74}], group: "Elephant"},
{data: [{text: "C", value: 63}, {text: "D", value: 1}], group: "Elephant"},
{data: [{text: "G", value: 72}, {text: "H", value: 74}], group: "Lion"},
{data: [{text: "M", value: 68}, {text: "N", value: 21}], group: "Lion"},
{data: [{text: "E",value: 37}, {text: "F", value: 54}], group: "Penguin"},
{data: [{text: "K", value: 76}, {text: "L", value: 38}], group: "Zebra"},
];
assert.deepEqual(got.toArray(), expected)
It's important to highlight that the TrueSet
is a sorted collection - a queue
, of simple items. The method toArray()
returns your original items, irrespective of their representation
in the TrueSet
internal tree structure. Nonetheless, such structure - a Classifier
, allows grouping and querying your original items based on their representation.
To become acquainted with the concepts of TrueSet
, Classifier
, and the representation
function, you might want to explore the ut8pia/classifier library.