基于每个其他元素对Javascript数组进行排序

时间:2015-09-30 07:31:56

标签: javascript arrays sorting

假设我有一个这样的数组:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];

偶数数组索引与以下奇数索引相关联。换句话说,94与" Neputunium"和2#" Helium"我如何根据偶数索引对数组进行排序,但在其后保留以下奇数索引值?所以我最终得到了一个像这样的数组:

a = [null, "Hypotheticalium", 2, "Helium", 64, "Promethium", 94, "Neptunium"];

注意:是的,我知道知道使用对象或ES6 Map(或者甚至,在这种情况下,使用数字作为索引的稀疏数组,如果省略null)会更合适,但我只是在探索这个来试验这门语言。谢谢你的帮助。

4 个答案:

答案 0 :(得分:5)

var grouped = [];
for (var i = 0; i < a.length; i += 2) {
    grouped.push([a[i], a[i+1]]);
}

grouped.sort(function (a, b) { return a[0] - b[0]; });

理想情况下,我建议您使用此处的grouped结构,因为将分组的项目组合在一起似乎更有意义,而不是依赖于隐式相邻索引。但如果你需要再打开包装:

var b = [];
for (var i = 0; i < grouped.length; i++) {
    b.push.apply(b, grouped[i]);
}

答案 1 :(得分:3)

由于sort的调用顺序不一定是下一个JavaScript引擎(甚至是同一引擎的转速之间),因此您无法使用sort 直接在该数组上执行您所描述的操作。

您可以使用mapfiltersort,然后使用reduce

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
  .map(function(entry, index, array) {
    return (index % 2 === 1) ? null : {
      value: array[index + 1],
      index: entry
    };
  })
  .filter(function(entry) {
    return entry != null;
  })
  .sort(function(left, right) {
    return left.index - right.index; // Works even when either or both
                                     // indexes are null, PROVIDED
                                     // no non-null index is negative,
                                     // because `null` will coerce to 0
  })
  .reduce(function(acc, entry) {
    acc.push(entry.index, entry.value);
    return acc;
  }, []);
document.body.innerHTML = JSON.stringify(a);

map让我们生成一个包含配对条目(和null s)对象的数组。

filter让我们删除null

sort让我们排序。

reduce让我们生成一个结果数组(因为我们不能直接使用map将一个条目映射到两个)。

如果你的偶数条目可能有负值,sort回调必须以不同的方式处理事情,因为它会将null排在那些负指数之上(当然除非你想要的)

在ES6中更简洁:( live on Babel's REPL

let a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
  .map((entry, index, array) => {
    return (index % 2 === 1) ? null : {
      value: array[index + 1],
      index: entry
    };
  })
  .filter(entry => entry != null)
  .sort((left, right) => left.index - right.index)
  .reduce((acc, entry) => {
    acc.push(entry.index, entry.value);
    return acc;
  }, []);
console.log(a);

答案 2 :(得分:1)

您需要对数组进行一些分组和适当的排序和重组。

var array = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"],
    sorted = array.reduce(function (r, a, i) {
        i % 2 ? r[r.length - 1].push(a) : r.push([a]);
        return r;
    }, []).sort(function (a, b) {
        return a[0] - b[0];
    }).reduce(function (r, a) {
        return r.concat(a);
    });
document.write('<pre>' + JSON.stringify(sorted, 0, 4) + '</pre>');

答案 3 :(得分:0)

我喜欢我给出的特定于JS的答案背后的想法,但这是我自己的解决方案,它不依赖于原生的sort功能,而是基于关于gnome sort的实施:

var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
for (var i = 0, temp; i < a.length; i += 2) {
    if (a[i] > a[i + 2]) {
        temp = a[i];
        a[i] = a[i + 2];
        a[i + 2] = temp;
        temp = a[i + 1];
        a[i + 1] = a[i + 3];
        a[i + 3] = temp;
        i = i - 4;
    }
}
alert(JSON.stringify(a));

当然,它不是最快的排序算法,而只是一个概念验证,表明它可以在不改变我的结构缺乏和没有大量​​(可能是昂贵的)函数调用的情况下完成(虽然我确实认为函数式编程更像是一个JS习语。我可以将交换代码放入自己的函数中,为了DRY,有两个调用,如下所示:

&#13;
&#13;
var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
function arraySwapper(array, index1, index2) {
    var temp = array[index1];
    array[index1] = array[index2], array[index2] = temp;
}
for (var i = 0, j; i < a.length; i += 2) {
    if (a[i] > a[i + 2]) {
        for (j = i; j < i + 2; j++) { arraySwapper(a, j, j + 2); }
        i -= 4;
    }
}
alert(JSON.stringify(a));
&#13;
&#13;
&#13;