对数组的字符串和数字进行排序,同时保持数组的原始顺序

时间:2017-05-15 15:15:19

标签: javascript arrays sorting

我刚刚接受了编码面试(呃),我不能为我的生活做出这样的决定。

问题

双重排序
请编写一个接受字符串数组的javascript方法。每个元素可以是数字(“165”)或单词(“dog”)。您的方法应该对数组进行排序和返回,使得(1)单词按字母顺序排列,数字按数字顺序排列,(2)数组中单词和数字的顺序相同。

示例(input => output):

排序(['5','4','狗','1','猫'))

=> ['1','4','猫','5','狗']

排序(['dog','cat'])

=> ['猫','狗']

排序('5','3')

=> ['3','5']

我能够编写一个基本排序函数,按字母顺序和数字顺序对数组进行排序,但是我无法维护数组的原始顺序。这是我设法在时间限制内提出的:

var multiSortArray = [5, 4, 'dog', 1, 'cat'];

var multiSort = function(arr) {
    var sortedArray = arr.sort();
    console.log(sortedArray);
}
multiSort(multiSortArray); 
which outputs: [1, 4, 5, "cat", "dog"]  

任何帮助都会受到赞赏,我很生气,因为我无法理解这一点。我在SO中找到的只是订购对象,我不确定是我需要做什么(或者我可以做。我不知道。)

谢谢大家!

6 个答案:

答案 0 :(得分:7)

只需将数字和单词拆分为单独的数组,对它们进行排序,然后重新加入



function sort(arr) {
  let n = arr.filter(x =>  isNaN(x)).sort((a,b) => a.localeCompare(b));
  let c = arr.filter(y => !isNaN(y)).sort((a,b) => a-b);

  return arr.map(z => (isNaN(z) ? n : c).shift());
}

console.log(sort(['5', '4', 'dog', '1', 'cat']));




答案 1 :(得分:2)

我想到的第一件事就是制作一张关于哪种类型的东西在哪个索引中的地图,然后将其分开并排序,然后根据类型将它们再次压缩在一起:

function sort(a) {
    const type = a.map(e => /^\d+$/.test(e));
    const nums = a.filter((e, i) => type[i]).sort((left, right) => left - right);
    const strs = a.filter((e, i) => !type[i]).sort((left, right) => left.localeCompare(right));
    let nindex = 0, sindex = 0;
    return type.map(t => t ? nums[nindex++] : strs[sindex++]);
}

console.log(sort(['5', '4', 'dog', '1', 'cat']));
// => ['1', '4', 'cat', '5', 'dog']

console.log(sort(['dog', 'cat']));
// => ['cat', 'dog']

console.log(sort(['5', '3']));
// => ['3', '5']

console.log(sort(['5', 'gazelle', '300']));
// => ['5', 'gazelle', '300']

function sort(a) {
    const type = a.map(e => /^\d+$/.test(e));
    const nums = a.filter((e, i) => type[i]).sort((left, right) => left - right);
    const strs = a.filter((e, i) => !type[i]).sort((left, right) => left.localeCompare(right));
    let nindex = 0, sindex = 0;
    return type.map(t => t ? nums[nindex++] : strs[sindex++]);
}
.as-console-wrapper {
  max-height: 100% !important;
}

或者使用ES5和更早的语法:

console.log(sort(['5', '4', 'dog', '1', 'cat']));
// => ['1', '4', 'cat', '5', 'dog']

console.log(sort(['dog', 'cat']));
// => ['cat', 'dog']

console.log(sort(['5', '3']));
// => ['3', '5']

console.log(sort(['5', 'gazelle', '300']));
// => ['5', 'gazelle', '300']

function sort(a) {
    var type = a.map(function(e) { return /^\d+$/.test(e); });
    var nums = a.filter(function(e, i) { return type[i]; }).sort(function(left, right) {
        return left - right;
    });
    var strs = a.filter(function(e, i) { return !type[i]; }).sort(function(left, right) {
        return left.localeCompare(right);
    });
    var nindex = 0, sindex = 0;
    return type.map(function(t) {
        return t ? nums[nindex++] : strs[sindex++];
    });
}
.as-console-wrapper {
  max-height: 100% !important;
}

...但是我已经向他们询问了一些有关数据的问题,因为如果有数十万条参赛作品,我可能会采取另一种方式。

另请注意确保数字的数字比较,以及字符串的正确词典比较(无论如何,在浏览器的功能集中)。

旁注:在我的版本中,我检测到了这样的数字:/^\d+$/.test(e)。这只允许整数,并且不允许科学记数法。另一种方法是改变adeneo所做的事情:e !== "" && !isNaN(e),如果数字不为空,则将e强制转换为数字并检查结果是否为NaN(这意味着它不能转换)。检查""是因为遗憾的是,强制""为号码会为您提供0,因此只有isNaN(e)会为""提供错误的结果。

答案 2 :(得分:2)

一种方法:



var arr = ['5', '4', 'dog', '1', 'cat'];

// STEP 1: split the original array into two arrays, one for strings and one for numbers
var str = [], num = [];
arr.forEach(e => isNaN(e)? str.push(e): num.push(e));

// STEP 2: sort the two arrays
str.sort();
num.sort((a, b) => a - b); // because the numbers are actually strings we need to do a - b to implicitly convert them into numbers and sort them using the substraction result

// STEP 3: for each element in the original array, if the original item was a string then replace it with the first item in the string array (and remove the added item), if the original item was a number, do the same with the num array
arr.forEach((e, i) => arr[i] = isNaN(e)? str.shift(): num.shift());

console.log(arr);




答案 3 :(得分:1)

这有点快,而且效率不高,但它是产生输出的一种潜在解决方案:

var sorter = function(array){
  let chars = [];
  let nums = [];

  array.forEach( (v,i) => {
    if(isNaN(+v)){
        chars.push(i);
    }
    else{
        nums.push(i);
    }
  });

  let newArray = [];

  let sortedChars = array.filter(a => isNaN(+a)).sort();
  let sortedNums = array.filter(a => !isNaN(+a)).sort();

  chars.forEach((value, index) => {
    newArray[value] = sortedChars[index];
  });

   nums.forEach((value, index) => {
    newArray[value] = sortedNums[index];
  });

  return newArray;
}

答案 4 :(得分:1)

这可以通过多种方式轻松完成,因此您可以将排序后的数组作为

[1,4,5,'cat','dog']

因此,在排序之前,请使用另一个相同大小的数组并制作标记

0 - means integer
1 - means string 

所以这个新数组看起来像这样

temp = [0, 0, 1, 0, 1];

现在你已经对它进行了重复迭代,然后按顺序将0替换为输入整数,用字符串替换为1

您将获得所需的输出。

答案 5 :(得分:1)

您可以将对象用于键入的值并进行相应的排序。然后再次使用原始数组并映射结果集的相同类型的值。

function sort(array) {
    var order = {
            number: function (a, b) { return a - b; },
            string: function (a, b) { return a.localeCompare(b); },
            default: function () { return 0; },
        };
        temp = {};

    array.forEach(function (a) { (temp[typeof a] = temp[typeof a] || []).push(a); });
    Object.keys(temp).forEach(function (t) { temp[t].sort(order[t] || order.default); });
    return array.map(function (a) { return temp[typeof a].shift(); });
};

console.log(sort([5, 4, 'dog', 1, 'cat']));
.as-console-wrapper { max-height: 100% !important; top: 0; }