7
  1. 我有一个数组。我整理一下。
  2. 我得到了第二个数组,它已经根据第一个数组进行了排序。

我需要反转第二个数组的排序。

例如,如果第一个数组(未排序)是:[9, 5, 3, 0, 2]那么我想对其进行排序,使其变为[0, 2, 3, 5, 9].

然后我收到基于第一个排序的第二个数组,例如["home", "car", "train", "pc", "mouse"]。我需要它变成["mouse, "pc", "train", "home", "car"].

我无法制作数组的副本。


我有以下代码:

//data_r is an array with values

var i = 0;
var sort_order = new Array();

data_r.sort(function (a,b) {
    var res = a[0] - b[0];
    
    sort_order[i] = res;
    i++;
    
    return res;
});

最后,sort_order数组将包含我们对项目进行排序时执行的操作。如果我想以与第一个数组完全相同的方式对第二个数组进行排序,那么我可以执行以下操作:

//data_x is an array with values

var i = 0;
data_x.sort(function (a,b) {
    i++;
    return sort_order[i-1];
});

现在data_x数组的排序方式与数组完全相同data_r

如何撤消对data_r数组的排序?

以下代码不正确:

var unsort = new Array();

for(var i = 0; i < data_r.length; i++)
    unsort[i] = sort_order[i]*(-1);//-1 so we perfom the oposite action
4

7 回答 7

12

你这里的前提是有缺陷的。

最后,sort_order 数组包含我们对项目进行排序时执行的操作。

不,它没有;它包含由 JavascriptArray.sort函数执行的比较的日志。它为响应这些比较结果而采取的行动是它私有的。

如果我想以与第一个数组完全相同的方式对第二个数组进行排序,那么我可以执行以下操作:

这不能保证有效。即使两个数组的大小Array.sort相同,每次调用时也可能并不总是以相同的顺序比较相同的元素 - 它可能使用随机算法,它根据解释器内部的其他数据执行比较,或者在某些情况下它会在多个完全不同的排序算法之间切换。

尽管此代码现在可能适用于您当前的 Web 浏览器,但在其他情况下(可能在未来的浏览器中)可能会以令人惊讶的方式失败。不要在生产代码中使用此技术。

问题是,我如何对 data_r 数组进行排序?

在对数组进行排序之前制作一个副本。

于 2013-07-11T16:15:17.927 回答
5

存储 res[i] = a - b 就像记录 sort() 算法——但是如果它使用随机枢轴呢?除非您自己编写 sort(),否则此代码本质上是不可靠的。这也是低效的。

一种更好的方法,一种可以同时解决您的需求的方法,是创建一个索引数组并对其进行排序。这是微不足道的反转。然后,您可以实现一个置换函数,该函数采用索引数组,并根据输入实现排序或取消排序。

如果 x 来自 0:n-1,则创建一个相同大小的数组 sort_i,然后初始化每个 sort_i[i] = i。

for(var i = 0; i < n; i++)
    sort_i[i] = i;

然后

sort_i.sort(function (a,b) { return x[a] - x[b]; });

现在你有了索引。应用于 x:

for(var i = 0; i < n; i++)
    sort_x[i] = x[sort_i[i]];

要取消排序,首先反转索引

for(var i = 0; i < n; i++)
    unsort_i[sort_i[i]] = i;

然后应用索引。练习留给提问者。

当您不想在内存中移动原始元素(可能它们是大对象)以及许多其他情况时,需要这种对整数索引数组进行排序的方法。基本上你正在对指针进行排序。结果是数据的索引和反向索引。

于 2013-07-11T16:30:14.140 回答
4

请参阅@duskwuff 的回答,了解您的方法为何不起作用。

相反,只需引入原始数据和排序数据之间的映射即可。

{0:2, 1:3, 2:1, 3:0}

这意味着第一个元素变成了第三个,第二个变成了最后一个,依此类推。下面我们将使用数组而不是对象。

为什么这张地图有帮助?您可以将其作为另一个数据集进行排序只需使用其中的 indizes 作为您要比较的数据的指针。您可以轻松地将映射应用于其他数据集。您甚至可以非常轻松地反转该映射。在代码中看到它:

// data_r, data_x are arrays with values

var l = data_r.length;
var sort_order = new Array(l);
for (var i=0; i<l; i++) sort_order[i] = i; // initialised as 1-1 mapping

// change the sort_order first:
sort_order.sort(function (a,b) {
    // a and b being indices
    return data_r[a] - data_r[b];
});
// Making a new, sorted array
var data_x_sorted = new Array(l);
for (var i=0; i<l; i++)
    data_x_sorted[ sort_order[i] ] = data_x[i]; // put it to sorted position

如果你想对data_x数组本身进行排序,只需使用我展示的“应用”算法data_r

问题是,如何撤消对data_r数组的排序?

要么根本不对其进行排序,而只是制作一个已排序的副本(或根本不做任何事情)。

或使用sort_order来反转它。您只需要在任何地方交换inewIndex( sortOrder[i]) 即可。构建一个新的“未排序”(旧顺序)数组的示例:

var unsorted = new Array(l);
for (var i=0; i<l; i++)
    unsorted[i] = data_r[ sort_order[i] ]; // take it from its new position
于 2013-07-11T17:12:07.650 回答
1

虽然这个问题此时已有 8 年历史,但我在尝试找到相同的解决方案时遇到了它,但我无法找到合适的、高效的和直观的方法,所以我自己写了一个。

请查看sort-unwind库。如果ranks是按顺序排列数组的索引列表...

import unwind from 'sort-unwind'

const suits = ['♥', '♠', '♣', '♦']
const ranks = [2, 0, 3, 1]

const [sortedSuits, tenet] = unwind(ranks, suits)
// sortedSuits <- ['♠', '♦', '♥', '♣']
// unwind <- [1, 3, 0, 2]

然后,您可以使用tenet返回的变量对数组进行排序并恢复原始顺序。

const names = ['spades', 'diamonds', 'hearts', 'clubs']
const [tenetNames, tenetRanks] = unwind(tenet, names)
// tenetNames <- ['hearts', 'spades', 'clubs', 'diamonds']
// tenetRanks <- [2, 0, 3, 1]
于 2021-03-11T06:26:06.787 回答
0

如果您有很多这样的数组要维护,那么最好将 array1 转换为对象数组,每个对象都包含值及其在数组中的原始位置。这将所有东西放在一个数组中。

var array1 = [9, 5, 3, 0, 2];
var array2 = ["home", "car", "train", "pc", "mouse"];

var sort = function(array){
    var indexed_objects =  array.map(function(value, index){
        return {index: index, value: value};
    });
    indexed_objects.sort(function(a,b){
        return a.value <= b.value ? -1 : 1;
    });
    return indexed_objects;
};

var sorted1 = sort(array1);
sorted1; // [{index: 3, value:0}, {index: 4, value: 2}, ...]

现在,给定一个排序对象数组,我们可以编写一个函数来相应地取消对任何其他数组的排序:

var unsort = function(array, sorted_objects){
    var unsorted = [];
    sorted_objects.forEach(function(item, index){
        unsorted[item.index] = array[index];
    });
    return unsorted;
};

var array2_unsorted = unsort(array2, sorted1);
array2_unsorted; // ["mouse", "pc", "train", "home", "car"]
于 2013-07-11T19:42:33.620 回答
0

排序函数只返回一个可以是正数、零或负数的数字,告诉它当前元素是否在它之前、具有相同的权重,或者在它正在比较的元素之后。由于您进行的比较次数,我想您的排序顺序数组比您的 data_r 数组长。我会在您对其进行排序之前复制 data_r ,然后在您希望它未排序时将 data_r 设置为等于该数组。

于 2013-07-11T16:16:45.863 回答
0

v1 = [0,1,2,3,4,5,6]
q = v1.length
b = []

for(i=0;i<q;i++){
	r = parseInt(Math.random()*v1.length)
	b.push(v1[r])
	a = v1.indexOf(v1[r])
	v1.splice(a,1)
}

于 2019-01-18T22:50:31.443 回答