【问题标题】:Sort an array to have duplicates at first and other elements afterwards (both in descending order) [duplicate]对数组进行排序以首先具有重复项,然后对其他元素进行排序(均按降序排列)[重复]
【发布时间】:2020-09-03 13:47:01
【问题描述】:

我正在尝试使用数组进行练习。以下是我想要实现的示例(让我们将其保留在 5 个元素的数组中):

[3,5,8,1,3] => [3,3,8,5,1]
[1,5,2,2,5] => [5,5,2,2,1]
[7,5,5,5,5] => [5,5,5,5,7]
[1,5,7,2,3] => [7,5,3,2,1]

我的尝试:

let myArr = [5,7,5,7,5];

function sortArr (arr) { 

  let sortedArr = [];
  let dupes = [];
  for (let i = 0; i <= arr.length-2; i++) {
    for (let j=i + 1; j <= arr.length-1; j++) {

      if (arr[i] == arr[j]) {
        if (sortedArr.some((element) => element == arr[i])) {
          sortedArr.push(arr[j]);
          dupes.push(j);
        } else {
          sortedArr.push(arr[i], arr[j])};
          dupes.push(j);
      }
      
    }
  }
  return sortedArr;
}

【问题讨论】:

  • "...尝试用数组练习"你的代码在哪里?
  • 欢迎来到 Stack Overflow!请使用tour(您将获得徽章!)并通读help center,尤其是How do I ask a good question? 您最好的选择是进行研究,search 以获取有关 SO 的相关主题,然后试一试. 如果您在进行更多研究和搜索后遇到困难并且无法摆脱困境,请发布您的尝试minimal reproducible example,并具体说明您遇到的问题。人们会很乐意提供帮助。
  • 第一次通过,计算每个值的出现次数。然后按occurances[value] &gt; 1降序排序。
  • 另外,不重复的条目应该如何排序?原始订单是否保留?当有多个重复时,应如何订购重复? (例如[1, 2, 1, 2, 3]。)你能依赖 ES2019 的变化,要求数组上的sort 是稳定的吗?
  • 你可以看这里(只是改变第一部分的顺序):stackoverflow.com/questions/58730313/…

标签: javascript arrays sorting filter


【解决方案1】:

首先用 Array#reduce 累加一个对象,其中数组中的每个值都是一个属性,所有它的出现。
从这里我得到值(例如 [3,3])和 Array#sort 他们用自定义比较器。在这里,我首先查找比较的数组的长度。如果两者相同,则比较值,否则数组具有更多元素。
最后我使用Array#flat 来平展阵列,我得到了想要的结果。

试用:https://jsfiddle.net/7p8wt4km/4/

function mySort(arr) {
  return  Object.values(arr.reduce((acc,cur) => {
      if (!acc[cur])
          acc[cur]=[cur];
      else
          acc[cur].push(cur);
      return acc;
  },{})).sort((a,b) => {
      lenA = a.length;
      lenB = b.length;
      return (lenA !== lenB) ? lenB- lenA : b[0] - a[0];
  }).flat();
}

console.log(mySort([3,5,8,1,3])); // [3,3,8,5,1]
console.log(mySort([3,5,8,1,3])); // [5,5,2,2,1]
console.log(mySort([7,5,5,5,5])); // [5,5,5,5,7]
console.log(mySort([1,5,7,2,3])); // [7,5,3,2,1]
console.log(mySort([1,5,2,2,7,2,7,2,5,3])); // [2, 2, 2, 2, 7, 7, 5, 5, 3, 1]

// This will work too
console.log(mySort([Number.MAX_SAFE_INTEGER,5,5,7,7,7,3, Number.MAX_SAFE_INTEGER,3,3,3,2,2,2,1]));
console.log(mySort([.00001,.00005,.00007,.00002,.00003,.00003,.00003]));

【讨论】:

  • 我用这个“if-block”检查累积的对象acc是否有一个带有键cur的属性的假值。我不想检查它的值是否不等于0。但是如果对象中不存在任何这样的键(因为!undefined 是true),这个条件也成立。如果您愿意,可以改用条件(!acc.hasOwnProperty(cur))。我检查这个是因为如果这个属性不存在,我会使用一个数组创建它,其中包含当前数据作为值。另一方面,如果它已经存在,那么我只需要将当前数据推送到此属性中的数组。
  • 这样我可以累积一个包含数组所有值的对象,并且每个属性都包含具有此名称的所有值。然后我可以使用这些属性进行排序。
  • sort((a, b) =&gt; b.length - a.length || b[0] - a[0])
【解决方案2】:

Array.prototype.sort() 可以有一个比较函数作为参数。

我首先用Array.prototype.reduce() 计算出现次数。然后我通过比较条目的计数和值进行排序

console.clear();

function sortArray(arr) {
  "use strict";
  
  var counts = arr.reduce((carry, elem) => {
    carry[elem] = ( carry[elem] || 0 ) + 1;
    return carry;
  }, {})
  return arr.sort((a, b) => (counts[b] == counts[a]) ? b - a : counts[b] - counts[a]);
}
console.log(sortArray([3,5,8,1,3]))
console.log(sortArray([1,5,2,2,5]))
console.log(sortArray([7,5,5,5,5]))
console.log(sortArray([1,5,7,2,3]))

console.log(sortArray([Number.MAX_SAFE_INTEGER,5,5,7,7,3, Number.MAX_SAFE_INTEGER,3,3,3,2,2,2,1]))
console.log(sortArray([.00001,.00005,.00007,.00002,.00003,.00003,.00003]))

【讨论】:

  • 这是一个巧妙的方法,通过与1E6 相乘来缩短排序算法,但这只适用于数组中的值不太大的情况。如果您希望始终在 安全 站点上使用 (counts[a] !== counts[b]) ? counts[b] - counts[a] : b - a;,就像我在解决方案中所做的那样。
  • @Sascha 你完全正确
  • sort((a, b) =&gt; counts[b] - counts[a] || b - a)
猜你喜欢
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 2019-06-26
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
相关资源
最近更新 更多