Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

119
Visualizações
How do I sort array by numbers and also prevent it from increasing more then 15 length and take only the biggest numbers?

here is my code for now:

router.get('/questions/best', function(req,res,next){
  Question.find({}).exec(function(err,results){
    if (err){return next(err)}
    let top15 = [];
    for(let i = 0; i< results.length; i++){
      let dislikestouse = results[i].dislikes[0]
      let ratio  = 0
      if(dislikestouse > 0){
        ratio = results[i].likes[0]/dislikestouse
      }
      else{
        ratio = results[i].likes[0]/1
      }
      
    }
    res.render('content', { whichOne: 5, user: req.user, questions: top15 });
  })
});

results is every question in the database, and top15 is supposed to be only the ones displayed since they have the highest ratio and rendered into the template. I tried using if statements to prevent it dividing by 0 since it results in an error.

how do I sort every result by finding if it is bigger then any of the items in top15 and then placing it in the right place if it is? I use pure JavaScript. to access the numbers of a result's dislikes and likes search for the first item since it where I store the length, like a typical likes array is: [2,'username1', 'username2']. here is the scheme for a question:

const Question = mongoose.model(
  "Question",
  new Schema({
    title: { type: String, required: true },
    text: { type: String },
    authorUsername: { type: String, required: true },
    dateCreated: {},
    answers: { type: Array, required: true },
    likes: { type: Array, required: true },
    dislikes: { type: Array, required: true },
    tag: { type: String, required: true },
    views: {type: Array, required:true},
  })
);

here is an example of a question:

_id:620935985f6865b4e85c333d
title:"How do i make a lemon?"
text:"yeet"
authorUsername:"SweetWhite"
dateCreated:2022-02-13T16:45:12.598+00:00
answers:
Array
likes:
Array
0:1
1:"SweetWhite"
dislikes:
Array
0:0
tag:
"Social"
views:
Array
0:1
1:"SweetWhite"
__v:0

Thanks!

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

You could use Array methods:

sort: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

slice: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

map: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Here is snippet i tried for your problem:

function sortQuestions(results) {
  const questionsWithRatio = results.map((result) => ({
    ...result,
    ratio: result.likes[0] / Math.max(result.dislikes[0], 1),
  }));
  // console.log(questionsWithRatio);
  const top15 = questionsWithRatio
    .sort((a, b) => b.ratio - a.ratio)
    .slice(0, 15);
  console.log(top15);
}
about 4 years ago · Juan Pablo Isaza Relatório

0

The answer above is a superb pure Javascript solution. However, it might be the case that we do not want to drag 1000s or possibly more of items out of the database just to sort and pick 15 on the client side. Given a set of docs like this:

var r =   [
    {likes: ['A','A'], dislikes: ['A','A']},
    {likes: ['A','A']},
    {dislikes: ['A','A']},
    {likes: ['A','A','A','A','A'], dislikes: ['A','A']},
    {likes: ['A','A','A','A','A','A','A','A','A'], dislikes: ['A','A']},
    {likes: ['A','A','A','A','A','A','A','A'], dislikes: ['A','A']},
    {likes: ['A','A','A','A','A','A','A'], dislikes: ['A','A']},
    {likes: ['A'], dislikes: ['A','A']}
];

Then here is an aggregation that will drive the sort and "slice" logic into the DB:

db.foo.aggregate([
    // Protect against missing fields with $ifNull                                                         
    // Protect against division by zero dislikes using max[1,size]                                         
    {$addFields: {ratio: {$divide:[{$size:{$ifNull:["$likes",[]]}},
                                 {$max:[1,{$size:{$ifNull:["$dislikes",[]]}}]}
                                ]}
               }},
    {$sort: {ratio:-1}},
    {$limit: 3}  // change to 15 for the real dataset
]);

If we must accomodate the "run length encoding" nature of the arrays e.g. [2, 'user1', 'user2'] then the agg is very similar only using $arrayElemAt to grab array[0] instead of using $size:

var r =   [
    {likes: [2, 'A','A'], dislikes: [2, 'A','A']},
    {likes: [2, 'A','A']},
    {dislikes: [2, 'A','A']},
    {likes: [5, 'A','A','A','A','A'], dislikes: [2, 'A','A']},
    {likes: [9, 'A','A','A','A','A','A','A','A','A'], dislikes: [2, 'A','A']},
    {likes: [8, 'A','A','A','A','A','A','A','A'], dislikes: [2, 'A','A']},
    {likes: [7, 'A','A','A','A','A','A','A'], dislikes: [2, 'A','A']},
    {likes: [1, 'A'], dislikes: [2, 'A','A']}
];

db.foo.aggregate([
    // Protect against missing fields with $ifNull but this time it is not
    // an empty array [] but rather an array of one elem, the length, which
    // is 0:                                                        
    {$project: {ratio: {$divide:[
        {$arrayElemAt:[{$ifNull:["$likes",[0]]}, 0]},
        {$max:[1, {$arrayElemAt:[{$ifNull:["$dislikes",[0]]}, 0]}]}
        ]}
    }},
    {$sort: {ratio:-1}},
    {$limit: 3}
]);

{ "_id" : 4, "ratio" : 4.5 }
{ "_id" : 5, "ratio" : 4 }
{ "_id" : 6, "ratio" : 3.5 }

about 4 years ago · Juan Pablo Isaza Relatório

0

Before I try to help, please try to improve your code's readability. You can look up async/await and ES6 syntax to help you in this.

Also, if you're using an IDE like Visual Studio Code then you can install prettier which will autoformat your codes.

Here's a rough solution for you:

router.get('/questions/best', function(req,res,next){
  Question.find({}).exec(function(err,results){
    if (err) return next(err);

    let top15 = [];

    // note that the code is slightly more readable already
    results.forEach(result => {
      const dislikesToUse = result.dislikes[0]

      let ratio = 0;

      if(dislikesToUse > 0) {
        ratio = result.likes[0]/dislikesToUse
      } else {
        ratio = result.likes[0]/1
      }

      // push each result with ratio to top15
      top15.push({...result, ratio})
    });

    // sort top15 by ratio
    top15.sort((a,b) => b.ratio - a.ratio) // do a.ratio - b.ratio to change order

    // get only the top 15
    top15 = top15.slice(0, 15)

    res.render('content', { whichOne: 5, user: req.user, questions: top15 });
  })
});

NOTE

This is only one way to do it and might not be the most efficient way. You should also consider Mongo's aggregate functions.

You should also definitely reconsider your schema design.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda