Как отсортировать элементы в массиве без изменения индексов других элементов?

У меня есть этот массив:

var arr = [5, 3, 2, 8, 1, 4];

Я пытаюсь отсортировать ТОЛЬКО элементы, которые имеют нечетные значения, поэтому я хочу это

выход:

[1, 3, 2, 8, 5, 4]

Как видите, четные элементы не меняют свою позицию. Кто-нибудь может сказать мне, что мне не хватает? Вот мой код:

function myFunction(array) {

  var oddElements = array.reduce((arr, val, index) => {
    if (val % 2 !== 0){
      arr.push(val);
    }
    return arr.sort();
  }, []);

  return oddElements;
}
console.log(myFunction([5, 3, 2, 8, 1, 4]));

Ответ 1

Сначала отсортируйте только нечетные числа и поместите его в массив oddSorted. Затем map каждый элемент в исходном массиве и проверьте, является ли текущий элемент нечетным, если нечетный, замените его на соответствующий отсортированный номер из массива oddSorted.

function sortOddElements(arr){
   var oddSorted = arr.filter(ele => ele %2 != 0).sort((a, b) => a - b);
   var evenNotSorted = arr.map((ele, idx) => {
       if(ele % 2 != 0){
           return oddSorted.shift(); 
       }
       return ele;
     });
   return evenNotSorted;
}
var arr = [5, 3, 2, 8, 1, 4];
console.log(sortOddElements(arr));
arr = [5, 3, 2, 8, 1, 4, 11 ];
console.log(sortOddElements(arr));

Ответ 2

Одним из вариантов является отслеживание признаков нечетных чисел в исходном массиве, а после .reduce и sorting затем выполнить итерацию по исходным нечетным числам и переназначить, взяв из отсортированного нечетного массива:

function oddSort(array) {
  const oddIndicies = [];
  const newArr = array.slice();
  const sortedOdd = array.reduce((arr, val, index) => {
    if (val % 2 !== 0) {
      arr.push(val);
      oddIndicies.push(index);
    }
    return arr;
  }, [])
    .sort((a, b) => a - b);
  while (oddIndicies.length > 0) {
    newArr[oddIndicies.shift()] = sortedOdd.shift();
  }
  return newArr;
}

console.log(oddSort([5, 3, 2, 8, 1, 4]));
console.log(oddSort([5, 3, 2, 8, 1, 4, 11 ]));

Ответ 3

Я немного изменил ваш код, чтобы выполнить вашу задачу. Посмотрите ниже

function myFunction(array) {

    var oddElements = array.reduce((arr, val, index) => {
        if (val % 2 !== 0) {
            arr.push(val);
        }
        return arr.sort(function(a, b){return a - b});
    }, []);

    var index = 0;
    var finalElements = [];
    for(var i=0; i<array.length; i++) {
        var element = array[i];
        if(element %2 !==0) {
            finalElements.push(oddElements[index]);
            index++;
        } else {
            finalElements.push(element);
        }
    }
    return finalElements;
}
console.log(myFunction([5, 3, 2, 8, 1, 4, 11]));

Ответ 4

Забавная проблема, спасибо, что поделились! Я думаю, что это простой подход -

const compare = (a, b) =>
  a < b ? -1
  : a > b ? 1
  : 0

const main = (arr) =>
{ const odds = []
  const idxs = []

  for (const [ i, x ] of arr.entries())
    if (x & 1)
      (odds.push(x), idxs.push(i))
  
  // odds = [ 5, 3, 11, 1 ] 
  // idxs = [ 0, 1, 4, 6 ]

  odds.sort(compare)
  // no need to sort idxs, always inserted in order

  // odds = [ 1, 3, 5, 11 ]
  // idxs = [ 0, 1, 4, 6 ]
  
  for (const [ i, x ] of odds.entries())
    arr[idxs[i]] = x
  
  return arr
}

console.log(main([ 5, 3, 2, 8, 11, 4, 1 ]))
// [ 1, 3, 2, 8, 5, 4, 11 ]