Reputation: 5199
I am looking to sort a JSON array of objects by the ascending order of values related to another value. Sounds confusing because it is. I have properties 'column' and 'order' in each object in an array. I need the order to be like: lowest number in column 1, lowest number in column 2, lowest number in column 3, second lowest number in column 1, second lowest number in column 2, second lowest number in column 3 and continue on. This is easy when 'order' has the exact same values, you can use a sort function like:
function sortCourses(a, b){
if (a.order == b.order) {
return (a.column - b.column);
} else {
return (a.order - b.order);
}
}
The problem is that I don't always have them setup like that. Here is an example array:
[
{
column: 2,
order: 5
},
{
column: 1,
order: 1
},
{
column: 3,
order: 2
},
{
column: 3,
order: 1
},
{
column: 1,
order: 4
},
{
column: 2,
order: 1
},
{
column: 3,
order: 3
},
{
column: 1,
order: 3
},
{
column: 2,
order: 3
},
{
column: 1,
order: 2
}
]
After sorting, I need this array to look like:
[
{
column: 1,
order: 1
},
{
column: 2,
order: 1
},
{
column: 3,
order: 1
},
{
column: 1,
order: 2
},
{
column: 2,
order: 3
},
{
column: 3,
order: 2
},
{
column: 1,
order: 3
},
{
column: 2,
order: 5
},
{
column: 3,
order: 3
},
{
column: 1,
order: 4
}
]
Any ideas on how I could accomplish this?
Upvotes: 3
Views: 124
Reputation: 211942
Could be a little faster, but hopefully easy to follow.
const data = [
{ column: 2, order: 5 }, { column: 1, order: 1 }, { column: 3, order: 2 },
{ column: 3, order: 1 }, { column: 1, order: 4 }, { column: 2, order: 1 },
{ column: 3, order: 3 }, { column: 1, order: 3 }, { column: 2, order: 3 },
{ column: 1, order: 2 }
];
// Sort by order.
data.sort(function (a, b) {
return (a.order - b.order);
});
// Group by column.
const groups = data.reduce(
function (acc, value) {
if (!acc[value.column]) {
acc[value.column] = [];
}
acc[value.column].push(value);
return acc;
}, {});
// Get sorted columns.
const cols = Object.keys(groups).map(Number).sort();
// Loop over columns taking lowest value until we're out of values.
const out = [];
while (out.length < data.length) {
cols.forEach(
function (col) {
if (groups[col].length) {
out.push(groups[col].shift(0));
}
});
}
console.log(out);
Upvotes: 3
Reputation: 12639
A fairly long winded way, but all I do is just group each 'group' (columns) into an object, pushing their orders into an array. Then I just sort them and paste them in.
var array = [
{
column: 2,
order: 5
},
{
column: 1,
order: 1
},
{
column: 3,
order: 2
},
{
column: 3,
order: 1
},
{
column: 1,
order: 4
},
{
column: 2,
order: 1
},
{
column: 3,
order: 3
},
{
column: 1,
order: 3
},
{
column: 2,
order: 3
},
{
column: 1,
order: 2
}
];
var new_array = {}
for (let item of array)
{
if (item.column in new_array)
{
new_array[item.column].push(item.order);
}
else
{
new_array[item.column] = [item.order];
}
}
let max = 0;
for (let key in new_array)
{
max = (max < new_array[key].length) ? new_array[key].length : max;
new_array[key].sort();
}
var final = [];
for (let i = 0; i < max; i++)
{
for (let key in new_array)
{
if (i < new_array[key].length)
{
final.push({column: key, order: new_array[key][i]});
}
}
}
console.log(final);
Upvotes: 1