从数组返回已排序的唯一值,但如果count相等,则按顺序返回值

时间:2017-07-19 19:51:38

标签: javascript arrays sorting unique

我正在创建一个函数,它接收一个未排序的整数数组,并返回一个唯一整数的数组,按频率排序。但是,如果整数具有相同的频率,则它们将以输入数组的原始顺序返回。这是我目前的职能:

function uniqueUnionSorted(arr) {
  counter = {};
  for(var i=0; i<arr.length; i++) {
    if (arr[i] in counter) {
      counter[arr[i]] ++;
    } else {
      counter[arr[i]] = 1;
    }
  }
  sortedStrings = Object.keys(counter).sort(function(a,b) {
    return counter[b] - counter[a]
  });
  var sortedNumbers = sortedStrings.map(Number);
  return sortedNumbers;
}

所以对于这样的数组:

arr = [1, 3, 2, 1, 5, 2, 1, 4]

该函数应返回:

[1,2,3,5,4]

但是,我的功能是对5和4进行排序并返回:

[1,2,3,4,5]

请帮忙!

4 个答案:

答案 0 :(得分:3)

此重新排序的原因是使用Object.keys()时,数字的对象属性将被排序。

不要将counter定义为对象,而是使用Map,它将保留插入顺序:

function uniqueUnionSorted(arr) {
  var counter = new Map();
  for(var i=0; i<arr.length; i++) {
    counter.set(arr[i], (counter.get(arr[i]) || 0) + 1);
  }
  // Spreading the Map will produce an array of pairs
  var sortedNumbers = [...counter].sort(function(a,b) {
    return b[1] - a[1]; // sort by count
  }).map(a => a[0]); // only keep the values, not the counts
  return sortedNumbers; // Map keys retain original type, so they remain numeric
}

arr = [1, 3, 2, 1, 5, 2, 1, 4]

console.log(uniqueUnionSorted(arr));

答案 1 :(得分:2)

在counter对象中,我们还可以保存每个元素的最低索引,这样我们就可以在排序数组中保留较低索引的元素。

function uniqueUnionSorted(arr) {
  counter = {};
  for(var i=0; i<arr.length; i++) {
if (arr[i] in counter) {
  counter[arr[i]].count ++;
} else {
  counter[arr[i]] = {'count' : 1, 'index' : i}; //save lowest index of element
}
  }
  sortedStrings = Object.keys(counter).sort(function(a,b) {
    return counter[b].count - counter[a].count || counter[a].index - counter[b].index;
  });
  var sortedNumbers = sortedStrings.map(Number);
  return sortedNumbers;
}

console.log(uniqueUnionSorted([1, 3, 2, 1, 5, 2, 1, 4]));

答案 2 :(得分:1)

draw up to a million points in real-time

这是使用Set对象,存储频率的对象和原始数组来保持原点不变的另一种方法。这比当前流行的答案要长一些,但是我正在写它,所以我想我会戴上帽子。

function sortArr(arr) {
  let uniqueValues = new Set();
  let frequencies = new Object();
//add values to set object
  arr.map((val) => uniqueValues.add(val));

//get frequencies of values
  for (let val of uniqueValues) {
    frequencies[val] = 0;
  }
  arr.map((val) => frequencies[val]++);

//sort by frequency, then sort by original placement in array
 let sorted_arr = Array.from(uniqueValues).sort((a, b) => {
    return frequencies[a] - frequencies[b];
  }).sort((a, b) => {
      return (frequencies[a] === frequencies[b]) ?
        Array.from(uniqueValues).indexOf(a) - Array.from(uniqueValues).indexOf(b) :
        b;
    });
//return array
    return sorted_arr;
  };

sortArr([1, 3, 2, 1, 5, 2, 1, 4]);  //1,2,3,5,4

修改 优化代码

答案 3 :(得分:0)

如果频率相等,可以添加一个额外的条件来实际排序原始数组索引:

sortedStrings = Object.keys(counter).sort(function(a,b) {
  return counter[b] - counter[a] || arr.indexOf(+a)-arr.indexOf(+b)
 });

http://jsbin.com/zewulanozo/edit?console