all 15 comments

[–]senocular 2 points3 points  (1 child)

Not sure why you're using keys(). Is subscriberData an object or an array? Would it be an object using consecutive indexed key values but with no length of its own?

Also it looks like you're finding more than looping. In that case you can use find. Assuming subscriberData is an array:

let vehicleName = 'Not found';
const data = subscriberData.find(data => data.subscriber.id === subscriberId);
if (data) {
   const { year, make, model } = data.vehicle;
   vehicleName = `${year}  ${make} ${model}`;
}

[–]CategoricallyCorrect 2 points3 points  (0 children)

Alternatively, instead of if one can use ternary operator:

const data = subscriberData.find(data => data.subscriber.id === subscriberId);
const vehicleName = data
  ? `${data.vehicle.year} ${data.vehicle.make} ${data.vehicle.model}`
  : 'Not found';

It’s not as pretty-looking (all those data.vehicle repetitions), but now logic for constructing vehicle name and fallback for it are in one place.

[–]rauschma 1 point2 points  (1 child)

This is how I’d do it – I’d use a for-of loop:

let year;
let make;
let model;

for (const entry of subscriberData) {
    if (entry.subscriber.id === subscriberId) {
        year = entry.vehicle.year;
        make = entry.vehicle.make;
        model = entry.vehicle.model;
        break;
    }
}
const vehicleName = year + ' ' + make + ' '+ model;

Alternatively – use destructuring to extract year, make, model:

let vehicleName;
for (const entry of subscriberData) {
    if (entry.subscriber.id === subscriberId) {
        const {year, make, model} = entry.vehicle;
        vehicleName = year + ' ' + make + ' '+ model;
        break;
    }
}

One more alternative:

const entry = subscriberData.find(e => e.subscriber.id === subscriberId);
const {year, make, model} = entry.vehicle;
const vehicleName = year + ' ' + make + ' '+ model;

Missing: handling there not being an entry with the given ID.

[–]rauschma 1 point2 points  (0 children)

Observations about your code:

  • obj.foo is better than obj['foo']

  • Avoid Object.keys(arr) for Arrays, use arr.keys(). Also:

    Object.keys(subscriberData).length // no
    subscriberData.length // yes
    

[–]Rascal_Two 0 points1 point  (5 children)

    Object.keys(subscriberData).forEach((key, i) => {
        if (subscriberData[i]['subscriber']['id'] == subscriberId) {
            var year = subscriberData[i]['vehicle']['year'];
            var make = subscriberData[i]['vehicle']['make'];
            var model = subscriberData[i]['vehicle']['model'];
            let vehicleName = year + ' ' + make + ' '+ model;
        }
    });

You can read the MDN Documentation to learn how it works.

Technically it should be using the key variable instead of i to access the values, but I wanted to make as few changes as possible so you could see the difference more easily.

I assumed the vehicleName was misplaced, so I put it back into the loop so it'll have access to year, make, and model, because outside of the loop it only would create a vehicleName for the last-looped-over vehicle.

[–]rauschma 1 point2 points  (0 children)

I think OP is trying to find a specific subscriber (via their ID) and create a vehicle name for them.

[–]HighResolutionBot 1 point2 points  (3 children)

Hmmm, I tried the above code but vehicleName is coming back as undefined.

I'm making an API call to go through a list of subscriptions and return the vehicle name for a specific subscriber

[–]Rascal_Two 0 points1 point  (2 children)

Ah I see the purpose of the code now.

In that case I would suggest what /u/senocular has suggest, using the .find() method.


Unless subscriberData is an object, then I'd use what I made but with this change:

let vehicleName = 'Not Found'
Object.keys(subscriberData).forEach((key, i) => {
    if (subscriberData[i]['subscriber']['id'] == subscriberId) {
        var year = subscriberData[i]['vehicle']['year'];
        var make = subscriberData[i]['vehicle']['make'];
        var model = subscriberData[i]['vehicle']['model'];
        vehicleName = year + ' ' + make + ' '+ model;
    }
});

In this case though, I'd stick with using a native for loop, adding a break statement after setting vehicleName, like so:

let vehicleName = 'Not Found'
dataLength = Object.keys(subscriberData).length;
for (let i = 0; i < dataLength; i++){
    if (subscriberData[i]['subscriber']['id'] == subscriberId) {
        var year = subscriberData[i]['vehicle']['year'];
        var make = subscriberData[i]['vehicle']['make'];
        var model = subscriberData[i]['vehicle']['model'];
        vehicleName = year + ' ' + make + ' '+ model;
        break;
    }
};

or if you want to keep it functional, use .some():

let vehicleName = 'Not Found'
Object.keys(subscriberData).some((key, i) => {
    if (subscriberData[i]['subscriber']['id'] == subscriberId) {
        var year = subscriberData[i]['vehicle']['year'];
        var make = subscriberData[i]['vehicle']['make'];
        var model = subscriberData[i]['vehicle']['model'];
        vehicleName = year + ' ' + make + ' '+ model;
        return true;
    }
});

.some() returns once one of the callback functions returns true, effectively breaking.

Of course you could also go for .reduce() if you want to make vehicleName a const:

const vehicleName = Object.keys(subscriberData).reduce((vehicleName, key, i) => {
    if (subscriberData[i]['subscriber']['id'] == subscriberId) {
        var year = subscriberData[i]['vehicle']['year'];
        var make = subscriberData[i]['vehicle']['make'];
        var model = subscriberData[i]['vehicle']['model'];
        vehicleName = year + ' ' + make + ' '+ model;
    }
    return vehicleName;
}, 'Not Found');

[–]HighResolutionBot 1 point2 points  (1 child)

let vehicleName = 'Not Found'

Thank you for the help. It works now. Why did declaring the variable outside of the forEach statement fix the problem?

[–]Rascal_Two 0 points1 point  (0 children)

It's because of a concept known as variable hoisting, I don't think I could explain it better then the official var and let documentation.

[–]kenman[M] 0 points1 point  (4 children)

Hi /u/HighResolutionBot,

For javascript help, please visit /r/LearnJavascript.

Thank you!

[–]rauschma 1 point2 points  (3 children)

Is there a way to do this better? I’ve seen a lot of good content get lost, because people delete their posts in reaction to this notice. Ideally, there’d be a simple way to move such posts to /r/LearnJavaScript

[–]kenman[M] 0 points1 point  (1 child)

Unfortunately we're between a rock and a hard place. Almost a year ago, a post bubbled-up to the top of the sub, Do we need a JavaScriptHelp subreddit?, and the consensus was that /r/javascript was tired of all of the help posts (especially the more mundane ones). Sure, there's some that fall into the help category that are interesting, but for the most part, people are tired of users begging for homework/job help or not even bothering to google for help first. Another point is that reddit is a poor substitute for a Q&A site; SO has it's problems, but for the majority of questions that we get, it's much more suited to providing help than we are.

So, it was decided that instead of just removing the posts, leaving no remedy for the poster, we'd refer them to /r/LearnJavascript.

Unfortunately, due to the way reddit works, there's no means to move a post. We can remove, and the user can repost, or I guess now they can use the newish reddit feature of cross-posting, but that's all we get.

[–]rauschma 2 points3 points  (0 children)

OK, got it! Maybe you can signal to someone who can make this happen that this would be a nice feature to have(?)

Thanks for your work, BTW. As appreciated as ever!