简体   繁体   中英

Javascript: Array iteration works on the second expression but not on the first

So I am importing the following things from a mongoDB database, on a node.js app I'm building, the block sections I'm going to post are all inside an asynchronous function, I'll try to post a console log for each of the objects I'm working with to see if anyone can explain this to me, but basically I have 2 array iterations, that build an object to be sent to the front-end as an array of objects, however the code sends the first object that matches my iterations and after that it returns a blank object , meaning that if I try to add more than object to the expected output it will only return one of the first element that the expression finds and it does not check for the rest of them.

Thanks in advance to anyone that can help me with this!

The objects I'm working with:

const about = await About.find(); //always has one document only so no conflict here
const allSkills = await Skill.find(); //grabs all the skills in the database
const skills = about[0].skillBag.filter((name) => name); //selects all the skills the user saved

Console logs:

console.log(allSkills) -> [
  {
    _id: 5fa59424f3d6532ae63fad26,
    category: 'Web Development',
    name: 'wordpress',
    path: 'wordpress.svg',
    __v: 0
  },
  {
    _id: 5fa5979c9e84032b92d3e9ee,
    category: 'DevOps',
    name: 'nginx',
    path: 'nginx.svg',
    __v: 0
  },
  {
    _id: 5fa597b79e84032b92d3e9ef,
    category: 'Web Development',
    name: 'javascript',
    path: 'javascript.svg',
    __v: 0
  },
.
.
.
]

console.log(skills) -> ["javascript","nginx"]

Since I've been trying to debug this for a while now I've built even separated the expressions to try to iterate on one array at a time:

//This lists all the skills with the category 'DevOps' 
//and builds an object from them with the output {name: 'nginx', path: 'nginx.svg'}
const allDevOpsSkills = allSkills
      .filter((e) => e.category == "DevOps")
      .map((n) => ({ name: n.name, path: n.path }));
// Does the same for the category 'Web Development'
const allWebDevSkills = allSkills
      .filter((e) => e.category == "Web Development")
      .map((n) => ({ name: n.name, path: n.path }));

These 2 expressions always return an array with the objects .map() builds Then I grab these 2 expressions and do:

const userDevOpsSkills = allDevOpsSkills.filter((n, i) => n.name == `${skills[i]}`);

// returns [ { name: 'nginx', path: 'nginx.svg' } ]

const userWebDevSkills = allWebDevSkills.filter((n, i) => n.name == `${skills[i]}`);

// returns [] and not [ { name: 'javascript', path: 'javascript.svg' } ]

I know I can do this in one expression instead of 2, that is the final version of my expressions however if I execute my code like the example above or if I run it like the example bellow the output is always the same

//Same expressions as above but in a more short way

    const userWebDevSkills = allSkills
      .filter((e) => e.category == "Web Development")
      .map((n) => ({ name: n.name, path: n.path }))
      .filter((n, i) => n.name == `${skills[i]}`);
    const userDevOpsSkills = allSkills
      .filter((e) => e.category == "DevOps")
      .map((n) => ({ name: n.name, path: n.path }))
      .filter((n, i) => n.name == `${skills[i]}`);

Extra info:

-The arguments that my current skills constant on the first code block returns are all stored in the database, but so that the post does not get any longer I redacted it, I want to do multiple checks on the same array.

I'm sorry if I can't explain myself any better, english is not my first language and I haven't been coding for that long to understand what exactly is going wrong in here.

Again thanks in advance to anyone that can help me with this!

EDIT Bellow is the code without been split into individual code blocks

const express = require("express");
const About = require("../models/aboutSchema");
const Skill = require("../models/skillSchema");
const { logger } = require("../controllers/logs");

const router = express.Router();

router.get("/", async (req, res) => {
  try {
    const path = req.originalUrl;
    const about = await About.find();
    const allSkills = await Skill.find();
    const skills = about[0].skillBag.filter((name) => name);
    
    const userWebDevSkills = allSkills
      .filter((e) => e.category == "Web Development")
      .map((n) => ({ name: n.name, path: n.path }))
      .filter((n, i) => n.name == `${skills[i]}`);
    const userDevOpsSkills = allSkills
      .filter((e) => e.category == "DevOps")
      .map((n) => ({ name: n.name, path: n.path }))
      .filter((n, i) => n.name == `${skills[i]}`);

    console.log(userWebDevSkills);
    res.status(200).render("home.ejs", {
      title: "Homepage | FilipeDev",
      user: req.user,
      path,
      about: about[0],
      webDev: userWebDevSkills,
      devOps: userDevOpsSkills,
    });
  } catch (e) {
    console.log(e);
    logger.error(e);
  }
});

module.exports = router;

If I understand your question, you are expecting:

const userWebDevSkills = allWebDevSkills.filter((n, i) => n.name == `${skills[i]}`);

to give you:

[ { name: 'javascript', path: 'javascript.svg' } ]

When I run this code:

const skills = ["javascript", "nginx"];

const allSkills = [{
        _id: 'fa59424f3d6532ae63fad26',
        category: 'Web Development',
        name: 'wordpress',
        path: 'wordpress.svg',
        __v: 0
    },
    {
        _id: 'fa5979c9e84032b92d3e9ee',
        category: 'DevOps',
        name: 'nginx',
        path: 'nginx.svg',
        __v: 0
    },
    {
        _id: 'fa597b79e84032b92d3e9ef',
        category: 'Web Development',
        name: 'javascript',
        path: 'javascript.svg',
        __v: 0
    },
];

const allDevOpsSkills = allSkills
    .filter((e) => e.category == "DevOps")
    .map((n) => ({ name: n.name, path: n.path }));

const allWebDevSkills = allSkills
    .filter((e) => e.category == "Web Development")
    .map((n) => ({ name: n.name, path: n.path }));

const userWebDevSkills = allWebDevSkills.filter((n, i) => n.name == `${skills[i]}`);

I do, indeed, get an empty array for userWebDevSkills and the issue is that allWebDevSkills ends up being this:

[
  { name: 'wordpress', path: 'wordpress.svg' },
  { name: 'javascript', path: 'javascript.svg' }
]

And, if skills is this:

["javascript","nginx"]

Then, this condition:

n.name == `${skills[i]}`

is never true so you never keep any items from the allWebDevSkills.filter() operation and thus end up with an empty array. I don't know exactly what you're attempting to do with the

n.name == `${skills[i]}` 

comparison so I'm' not sure exactly what to suggest to fix it, but this is demanding an exact position in the array match between allWebDevSkills and skills for the .name property and that doesn't happen. The javascript name property is in position 1 of allWebDevSkills , but in position 0 for the skills array and thus will never match your filter condition.


Also, code like this:

 n.name == `${skills[i]}`

can just be this:

 n.name === skills[i]

There is no need to put a single string into a ${} template by itself and === is favored when comparing strings (and not wanting to enable type conversion).


If what you're trying to do with the .filter() is to remove any items that don't have a .name property that is ANYWHERE in the skills array, then I would suggest this:

 const skills = ["javascript", "nginx"]; const skillsSet = new Set(skills); const allSkills = [{ _id: 'fa59424f3d6532ae63fad26', category: 'Web Development', name: 'wordpress', path: 'wordpress.svg', __v: 0 }, { _id: 'fa5979c9e84032b92d3e9ee', category: 'DevOps', name: 'nginx', path: 'nginx.svg', __v: 0 }, { _id: 'fa597b79e84032b92d3e9ef', category: 'Web Development', name: 'javascript', path: 'javascript.svg', __v: 0 }, ]; const allDevOpsSkills = allSkills .filter((e) => e.category == "DevOps") .map((n) => ({ name: n.name, path: n.path })); const allWebDevSkills = allSkills .filter((e) => e.category == "Web Development") .map((n) => ({ name: n.name, path: n.path })); const userWebDevSkills = allWebDevSkills.filter(n => skillsSet.has(n.name)); console.log(userWebDevSkills);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM