按照另一个数组的顺序对数组进行排序

6

我有一个数组,大小如下:

var arr = [
  'small',
  'small',
  'small',
  'small',
  ...
  'medium',
  'medium',
  'medium',
  'medium',
  ...
  'big',
  'big',
  ...
];

我需要按照这个顺序重新组织这个数组:

var order = ['small', 'small', 'medium', 'medium', 'big'];

因此,最终的结果会像这样:
var arr = [
  'small',
  'small',
  'medium',
  'medium',
  'big',

  'small',
  'small',
  'medium',
  'medium',
  'big'

  ...
];

我知道SO上有其他类似的问题,但目前我还没有找到任何东西。我不确定该如何处理它。我曾想过使用sort,但是我应该测试什么呢?这似乎很简单,但我卡住了,不知道从哪里开始。有什么提示吗?


我认为你需要展示数组在操作前后的实际例子。目前我看不出是什么导致数组在输出中分成了两组。 - mplungjan
使用另一个数组对数组进行排序?等等,什么意思? - Derek 朕會功夫
@Derek:随意编辑,不知道如何更好地定义这个问题... - elclanrs
1
@Derek:啊,这很有道理。太累了,连语义都想不清楚了... - elclanrs
@elclanrs - 你能否数一下有多少个“small”和“medium”,然后除以总数? - Derek 朕會功夫
6个回答

7

只需要为您的排序方法定义一个评分器即可。 以下是您的代码。试试看吧

var init_arr = ['small', 'big', 'big', 'medium'];

var scorer = {
   small: 0,
   medium: 1,
   big: 2
}

// You can use the same array too. I am creating new one.
var final_arr = init_arr.sort(function(a,b) {
   return scorer[a]-scorer[b];
});

alert(final_arr); //small, medium, big, big

Working Fiddle


非常好,比我的好+1。 - gdoron
@gdoron 很高兴你喜欢它 :) - Sachin Jain
2
很抱歉,这不是期望的结果。请参考示例。 - John Dvorak
我希望这是 OP 需要的,从他的输出示例来看,我认为我们缺少一些信息。 - mplungjan
@JanDvorak 对不起,我理解错了 :(。但是,我仍然会留下这个答案,以防它能帮到其他人。 - Sachin Jain
嗯,我不确定我理解了,但它不起作用。在这里检查演示http://jsbin.com/efuvop/4/edit - elclanrs

1
这个答案仅适用于您描述的确切情况,即数组长度是5的偶数倍,值按小、中、大排序,并且小和中的数量是大的两倍。
它可能适用于任何排序后的值数组,其中 length % 5 == 0,但结果可能不是您想要的。
function reOrder(array) {
  var result = [];
  var f = array.length/5; // this must be an integer
  var t;

  for (var i=0; i<f; i++) {
    t = i*2;
    result.push.call(result, array.slice(t, t+2));
    t = f*2 + i*2;
    result.push.call(result, array.slice(t, t+2));
    t = f*4 + i;
    result.push.call(result, array.slice(t, t+1));
  }
  return result; 
} 

var a = ['s','s','s','s','s','s','m','m','m','m','m','m','b','b','b'];
alert(reOrder(a)); // s,s,m,m,b,s,s,m,m,b,s,s,m,m,b

+1 这对我描述的情况似乎有效,但它比较随机,所以可能不适合长期的解决方案。 - elclanrs

1

好的,最终我找到了这个可行的解决方案:

function orderBy(arr, order) {
  var result = [],
      i = 0, len = arr.length,
      index;

  while (result.length < len) {
    index = arr.indexOf(order[i]);
    result.push(arr[index]);
    arr.splice(index, 1);
    i = i >= order.length-1 ? 0 : ++i;
  }

  return result;
}

它修改了原始数组,但这没关系。 演示:http://jsbin.com/umizat/1/edit

我很想知道这个的真实世界应用。 - mplungjan
@mplungjan:我有一个使用砌体网格的页面,其中包含了3个不同大小的盒子。为了创建一个完整的网格(没有空洞或奇怪的空白),这些盒子必须按照给定的模式排列(小,小,中,中,大)。这是总体的想法。最后,我选择用一个看起来"禁用"的盒子填充了这些空洞,而不是费劲地去解决这个问题。 - elclanrs
@elclanrs 哎呀,如果我之前看到这个问题就好了,我就不会浪费时间去制作我的代码片段和函数了><哈哈(你应该接受答案,这样像我这样发现问题有趣并创建一些东西的人就可以在查看所有答案之前就能工作:P) - Jon
尽管如此,值得一提的是,如果输入数组与顺序不完全匹配,它会返回“未定义”,而不是在末尾添加额外元素。但我有点怀疑你是否会有一个不完全符合顺序的数组。哈哈 - Jon

0

我知道这个问题很旧了,而且你已经有了一个正在使用的答案,但是我想提供这个例子和JSFiddle,以便解决您可能对结束进行的任何类型的修改。

注意:原始数组中剩余的任何内容都会添加到新数组的末尾,并且不会被排除。如果数组中没有足够的项来填充order的要求,则从顺序中跳过缺少的元素。

现在,进入函数:

function mySort(arr, order) {
    var newAr = [];
    var orIndex = 0;
    while(arr.length != 0) {
        var type = order[orIndex];
        var ind = arr.indexOf(type);
        if(ind != -1) {
            newAr.push(type);
            arr.splice(ind, 1);
        }
        orIndex++;
        if(orIndex >= order.length) {
            orIndex = 0;
        }
    }
    return newAr;
}

这个程序的作用是将你的示例数组:

var arrTest = [
  'small',
  'small',
  'small',
  'small',
  'small',
  'small',
  'small',
  'small',
  'medium',
  'medium',
  'medium',
  'medium',
  'medium',
  'medium',
  'medium',
  'medium',
  'big',
  'big',
  'big',
  'big',
];
var orderTest = ['small', 'small', 'medium', 'medium', 'big'];

现在,您可以随意更改它们,但它会对它们进行文本搜索,因此如果您希望对其进行排序,请确保完整数组和顺序数组中的内容相同。现在,要使用该函数,您需要执行以下操作:

var sortedArray = mySort(arrTest, orderTest);

或者,就像我在Fiddle中演示的那样:

alert(mySort(arrTest, orderTest).join('\n'));

这应该适用于涉及这两个方面的任何情况,而且顺序可以很容易地修改。

希望能有所帮助!


0
为什么不创建3个数组并根据大小拆分数据,然后您可以按给定顺序检索数据。
例如:
SMALL[];
MEDIUM[];
BIG[];

for(i,j,k : upto array lengths : i++,j++,k++){

   nwArray.add(SMALL[i]);
   nwArray.add(SMALL[++i]);
   nwArray.add(MEDIUM[j]);
   nwArray.add(MEDIUM[++j]);
   nwArray.add(BIG[k]);

}

return newArray;

0
我的方法是循环遍历订单数组,并提取元素,直到数组为空或不包含所需元素。
var sorted = [];
var arr = [
  'small',
  'small',
  'small',
  'small',
  ...
  'medium',
  'medium',
  'medium',
  'medium',
  ...
  'big',
  'big',
  ...
];
var order = ['small', 'small', 'medium', 'medium', 'big'];

out:
while (true) {
  for (var i = 0; i < order.length; i++) {
    var index = arr.indexOf(order[i]);
    if ((index === -1) or (arr.length === 0)) {
      break out;
    } else {
      var elem = arr.splice(index, 1);
      sorted.append(elem[0]);
    }
}

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