I need to sort array of objects by 2 conditions
- sort by value
- if names are the same show them next to each other in value order
Example example: https://codesandbox.io/s/relaxed-dhawan-sfryng?file=/src/index.js
CodePudding user response:
To sort an array of objects by multiple conditions, you can use the Array.prototype.sort()
method and provide a custom sorting function. The custom sorting function should take two objects as arguments and return a value indicating how they should be ordered in the sorted array.
Here is an example of how you might implement a custom sorting function that sorts the array by value, and then by name if the values are the same:
function sortByValueAndName(a, b) {
// If the values are different, sort by value
if (a.value !== b.value) {
return a.value - b.value;
}
// If the values are the same, sort by name
if (a.name !== b.name) {
return a.name < b.name ? -1 : 1;
}
// If both the values and the names are the same, the objects are equal
return 0;
}
// Example array of objects
const objects = [
{ name: "John", value: 10 },
{ name: "Jane", value: 10 },
{ name: "Alice", value: 5 },
];
// Sort the array using the custom sorting function
objects.sort(sortByValueAndName);
// The sorted array will be:
// [
// { name: "Alice", value: 5 },
// { name: "John", value: 10 },
// { name: "Jane", value: 10 },
// ]
Note that the sort() method modifies the array in place, so you don't need to assign the result of the sort() method to a new variable. The sorted array will be available in the same variable that you called sort() on.
CodePudding user response:
I provide a solution for it,it's a bit complexed,you can read the comment I have added
const array = [
{
name: "John",
value: 5
},
{
name: "David",
value: 6
},
{
name: "John",
value: 2
},
{
name: "Michael",
value: 4
}
];
const customSort = (data) => {
// create a new array to make elements have same name together
let newArray = data.reduce((a,v) => {
let obj = a.find(e => e.name === v.name)
if(obj){
obj.datas.push(v)
}else{
a.push({'name':v.name,'datas':[v]})
}
return a
},[])
// sort data in the new array by value
newArray.forEach(e => {
e.datas.sort((a,b) => a.value - b.value)
})
// create a value object with boolean value to avoid add duplicate element
let values = data.reduce((a,v) => {
a[v.value] = false
return a
},{})
let keys = Object.keys(values)
let result = []
for(k of keys){
// if the value has iterated,then skip it
if(values[k]){
continue
}
// find data by value
let arr = newArray.filter(e1 => e1.datas.some(e2 => e2.value == k)).flatMap(e => e.datas)
result.push(...arr)
// mark the value already added
arr.forEach(e => {
values[e.value] = true
})
}
return result
}
console.log(customSort(array))
CodePudding user response:
Hope it helps:
const arr = [
{
name: "John",
value: 5
},
{
name: "David",
value: 6
},
{
name: "John",
value: 2
},
{
name: "Michael",
value: 4
}
];
const groupByItems = [];
// Get index of the item based on name in groupByItems array
const getIndex = (name) => {
let index = -1;
groupByItems.forEach((groupByItem, _index) => {
if(groupByItem.name === name) {
index = _index;
}
});
return index;
}
// Group items by their name
const groupByName = () => {
arr.forEach((item) => {
const name = item.name;
const value = item.value;
let index = getIndex(name);
//Means that the [name] has not added before, so we should add it
if(index === -1) {
groupByItems.push({
name: name,
// Hold all values of the [name]
values: [],
// Hold minValue to sort groupByItems by that
minValue: Infinity
});
index = groupByItems.length - 1;
}
// Add current value to the list of values
groupByItems[index].values.push(value);
// Update minValue
if(groupByItems[index].minValue > value) {
groupByItems[index].minValue = value;
}
});
}
groupByName();
//Sort by minValue and then return final objects
const result = groupByItems.sort((a, b) => a.minValue - b.minValue).flatMap((item) => (
item.values.sort((firstValue, secondValue) => firstValue - secondValue).map((value) => {
return {
name: item.name,
value: value
}
})
));
console.log(result);