Click here to Skip to main content
14,690,839 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm a newbie. I'm struggling to construct this function within a function codes to extract the value in the nested array "shipName" that's within an array object using the .find() function. I was able to write these function codes, but how do I return the value of the variable "findIt" back to the calling function. Please correct me if my way of writing this function within the function code is out of place. Below are my codes. Currently, I'm getting a returned value of 'undefined'.

Your input and advice is truly appreciated. Thanks!

What I have tried:

const cruiseLines = [{
    Liner: 'Royal Carribean',
    shipName: ['Symphony of the Seas', 'Vision of the Seas']
},{
    Liner: 'Disney Cruise Line',
    shipName: ['Disney Magic', 'Disney Spinner', 'Disney Swan']
}]

const findShip = function (cruises, ships) {
    cruiseLines.forEach (function (cruiseLines, index){
        const findIt = cruiseLines.shipName.find(function (ship, index2){
            console.log(ship === ships)
        })
        return findIt
    })
    
}
const lookShip = findShip (cruiseLines.shipName, 'Disney Spinner')
console.log(lookShip)  
Posted
Updated 22-Feb-20 18:02pm

1 solution

Answer below, but some tips first:
1) It's generally a bad idea to declare anything const in the global scope.
2) You don't need to declare unused parameters in Javascript; it's chill like that.
3) Just because JS is chill and usually doesn't fuss about semicolons doesn't mean you shouldn't use them.
4) The Javascript MDN[^] is the single best resource (imo) for learning JS and also referencing how pretty much anything works in JS.
4a) The reason you get undefined is because forEach[^]'s return value is defined as undefined.

You almost had it. Use a nested find instead of forEach. forEach is for doing something to each element of a collection, not for finding and returning an element of a collection :) With some cleaning up and the fixes:
let cruiseLines = [{
    Liner: 'Royal Carribean',
    shipName: ['Symphony of the Seas', 'Vision of the Seas']
},{
    Liner: 'Disney Cruise Line',
    shipName: ['Disney Magic', 'Disney Spinner', 'Disney Swan']
}];

let findShip = function (targetShip){
    return cruiseLines.find(function (cruiseLine){
        return cruiseLine.shipName.includes(targetShip);
    });  
};
let lookShip = findShip('Disney Spinner');
console.log(lookShip);

If you don't want the entire object and just the name back (not sure why you'd want this, but re-reading your question I'm not sure):
let cruiseLines = [{
    Liner: 'Royal Carribean',
    shipName: ['Symphony of the Seas', 'Vision of the Seas']
},{
    Liner: 'Disney Cruise Line',
    shipName: ['Disney Magic', 'Disney Spinner', 'Disney Swan']
}];

let findShip = function (targetShip){
    let shipName;
    cruiseLines.forEach(function (cruiseLine){
        shipName = cruiseLine.shipName.find(function (ship){
            return ship === targetShip;
        });
    });  
    return shipName;
};
let lookShip = findShip('Disney Spinner');
console.log(lookShip);

If the above is what you want I'd go for this approach instead since you only need to know if the name exists, not what it is (you're already searching with the name):
let cruiseLines = [{
    Liner: 'Royal Carribean',
    shipName: ['Symphony of the Seas', 'Vision of the Seas']
},{
    Liner: 'Disney Cruise Line',
    shipName: ['Disney Magic', 'Disney Spinner', 'Disney Swan']
}];

let findShip = function (targetShip){
    for (let cruiseLine of cruiseLines)
      if(cruiseLine.shipName.includes(targetShip))
        return true;
    return false;
};
let lookShip = findShip('Disney Spinner');
console.log(lookShip);
   
v4
Comments
sonicJS 23-Feb-20 0:17am
   
Thank you so much Jon! This helped me greatly to understand more of how to code using functions and placement of variable to receive the returned value. I tested your suggestions and surely it worked. Thank you again.
sonicJS 24-Feb-20 22:07pm
   
Hi Jon,

After further testing, using the first solution, it correctly returns the shipNames that are listed under the Disney Cruise Line. But if I'm passing to the function argument any of the Roybal Carribean shipNames, it returned "undefined". I don't understand why . . .
Jon McKee 24-Feb-20 22:31pm
   
Where are you testing the Javascript? I'm using my browser console and it worked fine for me when I tested it just now.
sonicJS 29-Feb-20 10:51am
   
I'm running it using VS code.
Jon McKee 29-Feb-20 15:54pm
   
I would try debugging the code then: https://code.visualstudio.com/docs/editor/debugging

I can't reproduce the issue and I don't have VSCode.
sonicJS 29-Feb-20 15:58pm
   
Okay, I'll debug it . . .
sonicJS 29-Feb-20 22:10pm
   
During the debugging, I found out that Instead of skipping the function to compare other shipNames after it found "Vision of the Seas", it continued to compare more shipNames all the way to 'Disney Swan" which would result in "undefined" for console.log(lookShip).
Jon McKee 29-Feb-20 22:48pm
   
I think I may know what's going on, try this (works for me in the browser; explanation below):
let findShip = function (targetShip){    
  return cruiseLines.find(function (cruiseLine){        
    return cruiseLine.shipName.includes(targetShip);    
  });  
};

So I think this may have to do with type coercion. So the function that is passed into find should return a boolean to indicate that the value to return has been found. In the original code below, I've put the return types in brackets to illustrate:
let findShip = function (targetShip){    
  return [object] cruiseLines.find(function (cruiseLine){        
    return [string] cruiseLine.shipName.find(function (ship){            
      return [boolean] ship === targetShip;        
    });    
  });  
};

So what I'm used to with JS is that '', 0, -0, null, undefined, and NaN all convert to the boolean value false and everything else converts to true. But what might be happening for reasons I'm not sure of is that that second return type of string is converting to false for some reason, which is why the find keeps going.
sonicJS 2-Mar-20 20:42pm
   
Thanks for replying. I'm experimenting this now on how to stop .find() when the match is found.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900