如何在JavaScript大集合中进行排序和搜索

如何在JavaScript大集合中进行排序和搜索,javascript,sorting,search,Javascript,Sorting,Search,数组分数表示参与比赛的每个人的总分数。例如: User A: 100 points User B: 90 points User C: 90 points User D: 80 points User E: 75 points User F: 60 points 根据以上分数,我们将获得以下排名: User A: #1 User B: #2 User C: #2 User D: #3 User E: #4 User F: #5 此排序方法遵循密集排序方法 然后我们有一个名为alice的用

数组分数表示参与比赛的每个人的总分数。例如:

User A: 100 points
User B: 90 points
User C: 90 points
User D: 80 points
User E: 75 points
User F: 60 points
根据以上分数,我们将获得以下排名:

User A: #1
User B: #2  
User C: #2
User D: #3
User E: #4
User F: #5
此排序方法遵循密集排序方法

然后我们有一个名为alice的用户。如果她得到55分,根据上面的排名,她将排在第6位。 如果她得了90分,她将排名第二。等等

实际上,我有一个数组,其中包含alice的不同会话。例如: [55,90]

这意味着alice将首次排名第6位。而第二次她将排名第二

我把这个编码了,它能工作。然而,这似乎不是很有效。对于分数数组中有50万个条目的大型数据集,它会超时。代码如下:

const getPosition = (element, scores) => {
    scores.push(element);
    scores.sort(function (a,b) { return b-a; });
    return scores.indexOf(element)+1;
}

function climbingLeaderboard(scores, alice) {
    var uniqueSet = new Set(scores);
    scores = [...uniqueSet];
    var positions = [];
    let aliceIndex = 0;
    while(aliceIndex < alice.length){
        positions.push(getPosition(alice[aliceIndex], scores));
        aliceIndex++;
    }
    return positions;
}

function main() {
    const scores = [100, 90, 90, 80, 75, 60];
    const alice = [50, 65, 77, 90, 102];
    let result = climbingLeaderboard(scores, alice);
    console.log(result.join("\n") + "\n");
}
我猜排序函数和/或使用indexOf搜索数组中的元素就是问题所在。但是我找不到使这两个操作更有效的方法。

将getPosition函数更改为下面的函数,然后再试一次。刚刚删除了排序函数,并使用条件执行完整数组搜索

const getPosition=元素,分数=>{ 让长度=分数。长度; 设秩=1; forlet i=0;i元素{ 排名++; } } 返回等级; } 常量分数=[100,90,90,80,75,60]; 常数alice=[50,65,77,90102]; console.loggetPosition77,分数 将getPosition函数更改为下面的,然后重试。刚刚删除了排序函数,并使用条件执行完整数组搜索

const getPosition=元素,分数=>{ 让长度=分数。长度; 设秩=1; forlet i=0;i元素{ 排名++; } } 返回等级; } 常量分数=[100,90,90,80,75,60]; 常数alice=[50,65,77,90102];
console.loggetPosition77,分数 该方法假设在分数相等的情况下,Alice应在分数括号中排在第一位 这意味着如果她得了90分,那么她将排名第二,落后于100分,但高于其余的90分

function calculatePositions(scores, aliceScores) {
  let positions = [];
  const uniqueScoresSet = new Set([...scores]);
  const uniqueScoresArray = Array.from(uniqueScoresSet);

aliceScores.forEach((aliceScore) => {
    let position = uniqueScoresArray.findIndex((score) => aliceScore >= score);
    position = position === -1 ? scores.length : position + 1;
    positions.push(position);
  });

  return positions;
}

function main() {
  const scores = [100, 90, 90, 80, 75, 60];
  const alice = [50, 65, 77, 90, 102];
  let result = calculatePositions(scores, alice);
  console.log(result.join("\n") + "\n");
}

这种方法假设在分数相等的情况下,Alice应该排在分数框的最后一位 这意味着如果她得了90分,那么她将排在第四位,落后于100分和另外两个90分

function calculatePositions(scores, aliceScores) {
  let positions = [];
  aliceScores.forEach((aliceScore) => {
    let position = scores.findIndex((score) => aliceScore > score);
    position = position === -1 ? scores.length : position + 1;
    positions.push(position);
  });

  return positions;
}

function main() {
  const scores = [100, 90, 90, 80, 75, 60];
  const alice = [50, 65, 77, 90, 102];
  let result = calculatePositions(scores, alice);
  console.log(result.join("\n") + "\n");
}

该方法假设在分数相等的情况下,Alice应在分数括号中排在第一位 这意味着如果她得了90分,那么她将排名第二,落后于100分,但高于其余的90分

function calculatePositions(scores, aliceScores) {
  let positions = [];
  const uniqueScoresSet = new Set([...scores]);
  const uniqueScoresArray = Array.from(uniqueScoresSet);

aliceScores.forEach((aliceScore) => {
    let position = uniqueScoresArray.findIndex((score) => aliceScore >= score);
    position = position === -1 ? scores.length : position + 1;
    positions.push(position);
  });

  return positions;
}

function main() {
  const scores = [100, 90, 90, 80, 75, 60];
  const alice = [50, 65, 77, 90, 102];
  let result = calculatePositions(scores, alice);
  console.log(result.join("\n") + "\n");
}

这种方法假设在分数相等的情况下,Alice应该排在分数框的最后一位 这意味着如果她得了90分,那么她将排在第四位,落后于100分和另外两个90分

function calculatePositions(scores, aliceScores) {
  let positions = [];
  aliceScores.forEach((aliceScore) => {
    let position = scores.findIndex((score) => aliceScore > score);
    position = position === -1 ? scores.length : position + 1;
    positions.push(position);
  });

  return positions;
}

function main() {
  const scores = [100, 90, 90, 80, 75, 60];
  const alice = [50, 65, 77, 90, 102];
  let result = calculatePositions(scores, alice);
  console.log(result.join("\n") + "\n");
}

这是另一个镜头。。。也许不是最有效的方法,但请相信它确实有效。这实际上是乔纳斯·威尔斯对这个问题的评论的一种实现

这是一个蛮力解决方案,因为它为alice的每个分数遍历分数数组。更有效的方法是将alice的分数从最高到最低排序,但保持原始顺序,以便按正确的顺序组织结果,然后同时遍历分数数组和alice的数组

请注意,下面的解决方案根据问题运行测试用例,此外,还针对1M分数数组运行测试用例,该数组填充了99999到0之间的随机分数

函数爬升排行榜分数,alice{ 得分。排序a,b=>b-a; aliceRank=[]; 为了让aliceScore离开alice{ 设得分指数=0; 设秩=0; 而scoreIndex如果得分[scoreIndex]这里有另一种方法……也许不是最有效的方法,但请相信它能奏效。这实际上是乔纳斯·威尔斯对这个问题评论的一种实现

这是一种蛮力解决方案,因为它为alice的每个分数遍历分数数组。更有效的方法是将alice的分数从最高到最低排序,但保持原始顺序,以便按正确的顺序组织结果,然后同时遍历分数数组和alice的数组非常感谢

请注意,下面的解决方案根据问题运行测试用例,此外,还针对1M分数数组运行测试用例,该数组填充了99999到0之间的随机分数

函数爬升排行榜分数,alice{ 得分。排序a,b=>b-a; aliceRank=[]; 为了让aliceScore离开alice{ 设得分指数=0; 设秩=0; 而scoreIndexif scores[scoreIndex]将函数合并为一个函数。以{mark:rank}格式将rank作为对象返回

功能攀登排行榜 好的,爱丽丝{ 分数=[…新设置的核心]; 让长度=分数。长度; const rank=alice.reduceobj,key=>{ obj[key]=1; 返回obj; }, {}; 对于设i=0;i{ 如果得分[i]>项{ 排名[项目]++; } }; } 返回等级; } 常数分数=[]; 对于i=0;i<500000;i++{ 分数[i]=Math.floorMath.random*100; } 常数alice=[50,65,77,90102]; 让结果=上升排行榜分数,alice;
console.logresult 将您的函数合并为一个函数。以{mark:rank}格式将rank作为对象返回

函数爬升排行榜分数,alice{ 分数=[…新设置的核心]; 让长度=分数。长度; const rank=alice.reduceobj,key=>{ obj[key]=1; 返回obj; }, {}; 对于设i=0;i{ 如果得分[i]>项{ 排名[项目]++; } }; } 返回等级; } 常数分数=[]; 对于i=0;i<500000;i++{ 分数[i]=Math.floorMath.random*100; } 常数alice=[50,65,77,90102]; 让结果=上升排行榜分数,alice;

console.logresult;你不需要搜索。对数组排序,然后从左向右,每当出现另一个值时,将秩增加一。将索引分配给每个条目。@Jonaswillms您的意思是从alice列表中的最高值到最低值,对吗?然后从最高到最低搜索分数。我认为对你的建议唯一的调整是,如果alice碰巧有一个分数已经存在于分数中,那么就没有必要将排名提高1。@oderfla在分数数组中有50万个分数的情况下,分数是否仍然在0-100之间的整数值范围内?或者当你扩大到这个规模时,分数也会扩大吗?例如,如果你有50万分,你会得到10万分吗?@JonTrent不确定我是否理解你的问题。但大多数人似乎忽略的是,对于每个循环,我需要使用数组。因为每次Alice的附加值都只是暂时的。她将不再被包括在内,第二次,等等。重新划分范围:嗯,我在scrores数组中看到的第一个条目是99997617。所以我认为没有任何限制。你不需要搜索。对数组排序,然后从左向右,每当出现另一个值时,将秩增加一。将索引分配给每个条目。@Jonaswillms您的意思是从alice列表中的最高值到最低值,对吗?然后从最高到最低搜索分数。我认为对你的建议唯一的调整是,如果alice碰巧有一个分数已经存在于分数中,那么就没有必要将排名提高1。@oderfla在分数数组中有50万个分数的情况下,分数是否仍然在0-100之间的整数值范围内?或者当你扩大到这个规模时,分数也会扩大吗?例如,如果你有50万分,你会得到10万分吗?@JonTrent不确定我是否理解你的问题。但大多数人似乎忽略的是,对于每个循环,我需要使用数组。因为每次Alice的附加值都只是暂时的。她将不再被包括在内,第二次,等等。重新划分范围:嗯,我在scrores数组中看到的第一个条目是99997617。所以我认为没有任何限制。谢谢你。但是,您的解决方案都不起作用,。我的意思是,我得到了错误的结果。你试过了吗?@oderfla第一段代码产生了[7,5,4,2,1],据我所知,这是一个正确的结果。您预期的输出是什么。对不起,我忘了写预期的输出。然而,这正是我所期待的:6,5,4,2,1。另外,当我运行代码时,它的输出是:7,6,5,4,1@oderfla这是一个错误的情况下,分数是放在最后的位置。请在我编辑答案并运行第一个代码段时再次检查。输出是[6,5,4,2,1]对不起。我试了两种,但都不管用。他们都没有通过考试:谢谢你,伙计。但是,您的解决方案都不起作用,。我的意思是,我得到了错误的结果。你试过了吗?@oderfla第一段代码产生了[7,5,4,2,1],据我所知,这是一个正确的结果。您预期的输出是什么。对不起,我忘了写预期的输出。然而,这正是我所期待的:6,5,4,2,1。另外,当我运行代码时,它的输出是:7,6,5,4,1@oderfla这是一个错误的情况下,分数是放在最后的位置。请在我编辑答案并运行第一个代码段时再次检查。输出是[6,5,4,2,1]对不起。我试了两种,但都不管用。他们都没有通过测试:谢谢,但它仍然没有超时,和我的一样。谢谢,但它仍然没有超时,和我的一样。谢谢。但仍然不起作用。它仍然超时:/Hmmmm。。。您的环境一定有问题。在我的工作站Windows 10上,Chrome 83.0.4
103.97构建64位,运行时间不到1秒。谢谢。但仍然不起作用。它仍然超时:/Hmmmm。。。您的环境一定有问题。在我的工作站Windows 10上,Chrome 83.0.4103.97构建64位,运行时间不到1秒。