Home > Software design >  Sort array of objects by 2 conditions
Sort array of objects by 2 conditions

Time:12-03

I need to sort array of objects by 2 conditions

  1. sort by value
  2. 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);

  • Related