简体   繁体   English

我可以使用嵌套sort()对嵌套数组进行排序吗?

[英]Can i sort nested array using nested sort()?

This should be the input array 这应该是输入数组

var a = [2,1,3,4,1,[4,6,2,4],2,4,1];

For the output i have two cases :- (index of internal array is not changing) 对于输出,我有两种情况:-(内部数组的索引不变)

a = [1,1,2,3,4,[2,4,4,6],1,2,4]

and

a = [1,1,1,2,2,[2,4,4,6],3,4,4]

This is what i am trying to use :- 这就是我正在尝试使用的:-

a.sort(function(a,b){
  if(b instanceof Array){
    b.sort();
  }
})

You can loop over array and remove all sub arrays and save their index and then sort the new array and again push sorted sub arrays on specific indexes. 您可以遍历数组并删除所有子数组并保存其索引,然后对新数组进行排序,然后再次将排序后的子数组推入特定索引。

Sample 样品

 var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1]; var arr1 = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 6, 4, [4, 5, 3], 1, 2, 1, 3] var a = [2,1,3,4,1,[4,6,[4,5,[7,3,2,1,6],1,2],2,4],2,4,1]; function mySort(arr) { var _list = []; arr.forEach(function(item, index) { if (Array.isArray(item)) { _list.push({ index: index, value: arr.splice(index, 1).pop() }); } }); arr.sort(); _list.forEach(function(item) { arr.splice(item.index, 0, mySort(item.value)) }) return arr; } console.log(mySort(arr.slice())) console.log(mySort(arr1.slice())) console.log(mySort(a.slice())) 

Edit 1 编辑1

Inspired from joey-etamity 's answer, have made it generic for nested structure. 受到joey-etamity的回答的启发,使其成为嵌套结构的通用名称。

I suggest to splice the array if there is an element an array. 如果有数组元素,我建议拼接数组。 Then sort the array and reassemble the array. 然后对数组排序并重新组装数组。

This proposal iterates from the back and keeps the array intact while splicing. 该建议从背面进行迭代,并在拼接时保持阵列完整。

 function sort(array) { var i = array.length, inside = []; while (i--) { if (Array.isArray(array[i])) { inside.unshift({ pos: i, value: sort(array.splice(i, 1)[0]) }); } } array.sort(function (a, b) { return a - b; }); inside.forEach(function (a) { array.splice(a.pos, 0, a.value); }); return array; } var a = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1]; console.log(sort(a)); 

This is the perfect solution, use nested function invoke to sort array. 这是完美的解决方案,使用嵌套函数调用对数组进行排序。

Firstly , store all the array position and sub array. 首先,存储所有数组位置和子数组。

Secondly, extract numbers into new array, 其次,将数字提取到新数组中

Finally insert sorted array into same position as before. 最后,将排序后的数组插入到与以前相同的位置。

 var a = [2,1,3,4,1,[4,6,[4,5,[7,3,2,1,6],1,2],2,4],2,4,1]; function nestedSort(arr){ var items = []; var numArr = []; for ( key in arr){ if (arr[key] instanceof Array) { items.push({index:key,array:arr[key]}); }else{ numArr.push(arr[key]); } } numArr.sort(); for (key in items){ numArr.splice(items[key].index,0,nestedSort(items[key].array)); } return numArr; } console.log(nestedSort(a)); 

[
  1,
  1,
  1,
  2,
  2,
  [
    2,
    4,
    [
      1,
      2,
      [
        1,
        2,
        3,
        6,
        7
      ],
      4,
      5
    ],
    4,
    6
  ],
  3,
  4,
  4
]

Hope this can solve your problem. 希望这可以解决您的问题。 :) :)

Array.sort() is not built to handle partial Arrays, what you would need in your case, but we can work around this problem by pre-processing the data (wrapping it with additional information), then sorting and at the end, extracting the original values: Array.sort()并非用于处理部分Array,这是您需要的,但是我们可以通过预处理数据(将其与其他信息包装在一起),然后进行排序并最后进行提取,来解决此问题。原始值:

case 1: sorting the parts between the Arrays 情况1:对数组之间的部分进行排序
[2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,2,3,4,[2,4,4,6],1,2,4] [2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,2,3,4,[2,4,4,6],1,2,4]

function sort1(arr){
    //I add an artificial "property" of to the values, to "describe" the groups, and to be able to sort by
    //each Array is it's own group (so they stay in order), and the values in between share the same group
    var group = 0, 
        isArray = false;

    //an intermediate Array holding all the information (in order) to either apply it to the current Array, or to return (map) it as a new Array
    var intermediate = arr.map(function(v,i){
        //last value was an Array, this is the first value after an Array, start a new group
        if(isArray) ++group;    

        if(isArray = Array.isArray(v)){ //update isArray
            v = sort1(v);               //recursive sorting
            ++group;                    //the last group just ended here
        }

        //return a composition, that contains all the data I need to sort by
        return {
            group: group,
            value: v
        }
    }).sort(function(a, b){
        //forst sort by group, and (only) if two values share the same group, sort by the original value
        return a.group - b.group || a.value - b.value
    });

    //apply data to current Array
    intermediate.forEach(function(obj, i){ arr[i] = obj.value });
    return arr;

    //return new Array
    //return intermediate.map(function(obj){ return obj.value });
}

case 2: treating an Array like it's first value 情况2:将Array视为第一个值
[2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,1,2,2,[2,4,4,6],3,4,4] [2,1,3,4,1,[4,6,2,4],2,4,1] -> [1,1,1,2,2,[2,4,4,6],3,4,4]

function sort2(arr){
    //an utility to fetch the first non-array value recursively
    function _value(v){ 
        while(Array.isArray(v)) v = v[0];
        return v;
    }

    var intermediate = arr.map(function(v, i){
        if(Array.isArray(v)) v = sort2(v);
        return {
            index: i,
            value: v,
            sortingValue: _value(v)
        }
    }).sort(function(a, b){
        return a.sortingValue - b.sortingValue || a.index - b.index;
    });

    //apply data to current Array
    intermediate.forEach(function(obj, i){ arr[i] = obj.value });
    return arr;

    //return new Array
    //return intermediate.map(function(obj){ return obj.value });
}

No, you don't put the sort call in the comparison function. 不,您没有将sort调用放入比较函数中。 You would recurse through your arrays, bottom to top, and sort them one after the other. 您将自下而上地遍历数组,并将它们一个接一个地排序。 In your case you might not even need recursion if it's only one array in another: 在您的情况下,如果它只是另一个数组中的一个,则可能甚至不需要递归:

a.forEach(function(element) {
   if (Array.isArray(element))
       element.sort(function compare(a, b) { return a-b; });
})

(I've chosen a simple numerical compare here). (我在这里选择了一个简单的数值compare )。

Then you'd sort the outer array: 然后对外部数组进行排序:

a.sort(function compare(a, b) {
    if (Array.isArray(a)) a = a[0];
    if (Array.isArray(b)) b = b[0];
    return a - b;
})

(here compare takes the first element of the array to compare by that against the other numbers). (在这里, compare将数组的第一个元素与其他数字进行比较)。

I think this would be better to use Array.prototype.sort this way: 我认为这样使用Array.prototype.sort会更好:

 // var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 4, 1]; var arr = [2, 1, 3, 4, 1, [4, 6, 2, 4], 2, 6, 4, [4, 5, 3], 1, 2, 1, 3]; var chunks = chunkate(arr) console.log(JSON.stringify(chunks)); chunks.forEach(ch => ch.sort(_sort)); var result = chunks.reduce((p, c) => p.concat(c)); console.log(JSON.stringify(result)); function _sort(a, b) { var isAa = Array.isArray(a), isAb = Array.isArray(b); isAb && b.sort(_sort); return (isAa || isAb) ? 0 : a - b; } function chunkate(arr) { return arr.reduce((a, c) => { Array.isArray(c) ? a.push(chunkate(c), []) : a[a.length - 1].push(c) return a; }, [[]]); } 

How it works? 这个怎么运作?

If items to compare are are array then they shouldn't be replaced so by sending false sort function recognize that there is no need to replace. 如果要比较的项目是数组,则不应替换它们,因此通过发送false排序函数可以识别出无需替换。 Otherwise the simple compare is the answer. 否则,简单的比较就是答案。

Edit 编辑

As discussed in comments, it's better to separate values to chunks and then sort each part then join parts again. 正如评论中所讨论的,最好将值分隔为多个块,然后对每个部分进行排序,然后再次合并部分。 If nesting depth is only one level you can use default sort (without _sort function) but be aware of array in array used for nested array. 如果嵌套深度仅为一级,则可以使用默认排序(不带_sort函数),但要注意用于嵌套数组的数组中的数组。 So the sort should be changed like this: 所以排序应该像这样改变:

chunks.forEach(ch => Array.isArray(ch[0])? ch[0].sort(): ch.sort());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM