Как реализовать сортировку по вложенному массиву с ключами и порядком сортировки - PullRequest
1 голос
/ 18 июня 2019

Я пытаюсь реализовать множественную сортировку для вложенного массива на основе ключей и порядка сортировки.

Я могу сортировать массив на основе ключа и порядка

У меня естьсделал следующий код для сортировки по массиву,

return array.sort((a, b) => {
      let i = 0, result = 0;
      while (i < sortBy.length && result === 0) {
        if (typeof a[sortBy[i].prop] == "string") {
          result = sortBy[i].direction * (a[sortBy[i].prop].toString() < b[sortBy[i].prop].toString() ? -1 : (a[sortBy[i].prop].toString() > b[sortBy[i].prop].toString() ? 1 : 0));
        } else {
          result = sortBy[i].direction * (a[sortBy[i].prop] < b[sortBy[i].prop] ? -1 : (a[sortBy[i].prop] > b[sortBy[i].prop] ? 1 : 0));
        }
        i++;
      }
      return result;
    });

Мои входные данные приведены ниже,

array = [{ x: [{ d: 4 }, { d: 2 }, { d: 3 }, { d: 1 }], b: 'v' }, { x: [{ d: 8 }, { d: 7 }, { d: 5 }, { d: 6 }], b: 's' }];
sortBy= [{ 'prop': 'b', 'direction': 1 }, { 'prop': 'd', 'direction': 1}];

Я ожидал вывод, подобный приведенному ниже,

array = [{ x: [{ d: 5 }, { d: 6 }, { d: 7 }, { d: 8 }], b: 's' },{ x: [{ d: 1 }, { d: 2 }, { d: 3 }, { d: 4 }], b: 'v' }];

Но я получаю следующий результат:

array = [{ x: [{ d: 8 }, { d: 7 }, { d: 5 }, { d: 6 }], b: 's' },{ x: [{ d: 4 }, { d: 2 }, { d: 3 }, { d: 1 }], b: 'v' }];

Я застрял на том, как решить эту логическую проблему.Может ли кто-нибудь помочь мне в этом.

Ответы [ 2 ]

1 голос
/ 18 июня 2019

Из того, что я вижу, вам нужно сделать это рекурсивным и вызывать функцию всякий раз, когда вы нажимаете массив в вашем объекте.Взгляните на это

let input = [
{ x: [{ d: 4 }, { d: 2 }, { d: 3 }, { d: 1 }], b: 'v' }, 
{ x: [{ d: 8 }, { d: 7 }, { d: 5 }, { d: 6 }], b: 's' }
];

const sortingInstructions = [
  {prop: 'b', direction: 1},
  {prop: 'd', direction: 1}
];

const isArray = Obj => {
  return typeof(Obj) === 'object' && Obj.length !== undefined
}

const nestedSort = SortingArray => {
  for(let obj of SortingArray){
  	for(let key of Object.keys(obj)){
    	if(isArray(obj[key])){
        nestedSort(obj[key])
      }
    }  	
  }
  for(let instruction of sortingInstructions){

    SortingArray.sort((a,b) => {
      if(typeof(a[instruction.prop]) === 'string'){
        return instruction.direction*b[instruction.prop].localeCompare(a[instruction.prop])
      }
      if(typeof(a[instruction.prop]) === 'number'){
        return instruction.direction*(b[instruction.prop]-a[instruction.prop]);
      }
    })
  }
	
  
  return SortingArray;
}

nestedSort(input);
console.log(input);

Это делается следующим образом.

  1. если вы нажмете массив в своем объекте, вы вызовете функцию рекурсивно для этого массива

  2. вы сортируете массив по всем вашим инструкциям (те, что находятся ниже в ваших инструкциях, являются доминирующими, поскольку они используются для сортировки последних)

  3. если то, что вы нажимаете, является строкой, вы используете localeCompare для ее сортировки

Поскольку это рекурсивно, оно также будет работать на любой глубине объекта.Например,

let input = [
  { x: [{y:[{ d: 4 }, { d: 2 }, { d: 3 }, { d: 1 }]}], b: 'v' }, 
  { x: [{z:[{ d: 8 }, { d: 7 }, { d: 5 }, { d: 6 }]}], b: 's' }
]

также будет работать

1 голос
/ 18 июня 2019

Вы близки, вам нужно вызвать метод сортировки для внутренних массивов со свойством x.Затем послесловия вызывают его в исходном массиве.При этом сначала будут отсортированы подмассивы со свойством d, а затем внешний массив послесловия: b.

array = [{ x: [{ d: 4 }, { d: 2 }, { d: 3 }, { d: 1 }], b: 'v' }, { x: [{ d: 8 }, { d: 7 }, { d: 5 }, { d: 6 }], b: 's' }];
sortBy= [{ 'prop': 'b', 'direction': 1 }, { 'prop': 'd', 'direction': 1}];

function sortFunc(a, b) {
  let i = 0, result = 0;
  while (i < sortBy.length && result === 0) {
    if (typeof a[sortBy[i].prop] == "string") {
      result = sortBy[i].direction * (a[sortBy[i].prop].toString() < b[sortBy[i].prop].toString() ? -1 : (a[sortBy[i].prop].toString() > b[sortBy[i].prop].toString() ? 1 : 0));
    } else {
      result = sortBy[i].direction * (a[sortBy[i].prop] < b[sortBy[i].prop] ? -1 : (a[sortBy[i].prop] > b[sortBy[i].prop] ? 1 : 0));
    }
    i++;
  }
  return result;
}

array.forEach(arr => arr.x = arr.x.sort(sortFunc));
array = array.sort(sortFunc);
console.log(array);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...