katie hudson
katie hudson

Reputation: 2893

Ordering Array using a defined order

I am trying to format some data for Google Charts. My initial array is quite large containing quite a bit of data. As such, I use the reduce function like so

const dataFormatted = this.graphData.grouping.reduce((acc, item, index) => {
    acc.push([item.category, item.average, this.columnOptions.colors[index], item.average])
    return acc
}, [
    ['category', 'average', { role: 'style' }, { role: 'annotation' }]
])

So when this is complete, I end up with an array like so

[
    ["category","average",{"role":"style"},{"role":"annotation"}],
    ["High",0.0511,"#487090",0.0511],
    ["Low",0.0177,"#EFCA08",0.0177],
    ["Medium",0.03,"#F08700",0.03],
    ["Very High",0.2797,"#FF595E",0.2797],
    ["Very Low",0.0096,"#00A6A6",0.0096]
]

The first row will always be what it is, this is for Google Charts. However, the rows after this, I wanted in the following order

const ordering = ['Very Low', 'Low', 'Medium', 'High', 'Very High']

So I essentially need dataFormatted to end up like this

[
    ["category","average",{"role":"style"},{"role":"annotation"}],
    ["Very Low",0.0096,"#00A6A6",0.0096]
    ["Low",0.0177,"#EFCA08",0.0177],
    ["Medium",0.03,"#F08700",0.03],
    ["High",0.0511,"#487090",0.0511],
    ["Very High",0.2797,"#FF595E",0.2797],
]

I have tried different things, including checking the value in the reduce function and then using splice on acc, but even this seems to go wrong. My latest attempt is

const ordering = ['Very Low', 'Low', 'Medium', 'High', 'Very High']
var itemsOrdered = []
for (var i = 0; i < ordering.length; i++) {
  if (dataFormatted.indexOf(ordering[i]) > -1) {
    itemsOrdered.push(ordering[i])
  }
}
console.log(itemsOrdered)

But itemsOrdered then prints out an empty array. So what would be the best way to order this array in the way I require?

Thanks

Upvotes: 1

Views: 42

Answers (2)

CertainPerformance
CertainPerformance

Reputation: 370639

Sort the array after extracting the values, not while transforming it, then add on the first item:

const graphData = this.graphData.grouping.map(
    (item, index) => ([item.category, item.average, this.columnOptions.colors[index], item.average])
);
const ordering = ['Very Low', 'Low', 'Medium', 'High', 'Very High'];
graphData.sort((a, b) => ordering.indexOf(a[0]) - ordering.indexOf(b[0]));
const headers = ['category', 'average', { role: 'style' }, { role: 'annotation' }];
const output = [headers, ...graphData];

Upvotes: 3

Nina Scholz
Nina Scholz

Reputation: 386520

You could keep the header with an own order.

const
    array = [["category", "average",{"role":"style"},{"role":"annotation"}], ["High",0.0511,"#487090",0.0511], ["Low",0.0177,"#EFCA08",0.0177], ["Medium",0.03,"#F08700",0.03], ["Very High",0.2797,"#FF595E",0.2797], ["Very Low",0.0096,"#00A6A6",0.0096]],
    order = { category: 1, 'Very Low': 2, Low: 3, Medium: 4, High: 5, 'Very High': 6 };

array.sort(([a], [b]) => order[a] - order[b]);

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions