如何在不改变其他元素索引的情况下对数组中的元素进行排序?

13

我有这个数组:

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]));

我知道我可以使用slice向数组添加元素,但我不知道如何获取索引并将元素放入数组中。

3个回答

8

首先,只对奇数进行排序并放入数组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!= 0”计算两次的情况下完成吗? :D - Mulan
我想到的一件事是检查当前元素是否包含在 "oddSorted" 数组中,如果是,则用 "oddSorted" 数组中的第一个数字替换当前数字。这也可以作为一个判断条件,即如果当前元素包含在 "oddSorted" 数组中,则说明该数字为奇数,因此无需再次检查它。但是您认为这样会提高性能吗? - Fullstack Guy
你不需要克隆 arr。无论如何,过滤器都会返回一个新的数组。 - kremerd

5

一种方法是跟踪原始数组中奇数的索引,然后在 .reduce 和排序之后,通过迭代原始奇数索引并重新分配,从排序后的奇数数组中获取:

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 ]));


你的解决方案在我传递这个数组时不起作用:[5, 3, 2, 8, 1, 4, 11],它应该返回[1, 3, 2, 8, 5, 4, 11],但它返回[1, 11, 2, 8, 3, 4, 5]。 - Devmix
啊,11 会使 .sort 函数按字典排序,这会导致问题 - 改用自定义的 .sort 函数,见编辑部分。 - CertainPerformance

0

我稍微修改了你的代码以达到你的目标。请看下面

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]));

记住,默认的排序函数是按字母顺序排序值的。这就是为什么你不能只使用arr.sort()。


不行,你的解决方案在我传递这个数组时不起作用:[5, 3, 2, 8, 1, 4, 11],它应该返回[1, 3, 2, 8, 5, 4, 11],但它返回[1, 11, 2, 8, 3, 4, 5]。 - Devmix
好的...我正在查看它。 - Tanmoy Krishna Das
问题出在排序函数上。默认的排序函数按字母顺序排序。这就是为什么你不能只使用arr.sort()。我修改了代码以反映您的需求。 - Tanmoy Krishna Das

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接