Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

118
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda