iteration of a JSON containg objects - javascript

I am trying to write a function that takes pokemon’s name as an argument and find out which all pokemon have that name in their “next_evolution” field
Consider the following JSON dataset -
visit https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json
now for that, I've written the following function:
var infoOfPokemon = function(nameOfPokemon,allPokemon){
for(x in allPokemon){
if(allPokemon[x].next_evolution.includes(nameOfPokemon)){
console.log('pokemons found: '+allPokemon[x].name)
} else{
null
}
}
}
var nameOfPokemon =prompt('enter the name of Pokemon')
infoOfPokemon(nameOfPokemon,pokemonData.pokemon)
but it is returning an error which says
Uncaught TypeError: Cannot read property 'includes' nextEvolution.js:4090 of undefined

One or more of your pokemon does not have a 'next_evolution' field set (for example, the one with id 3 in your file). Hence allPokemon[x].next_evolution evaluates to undefined and you cannot read 'includes' on that.
Check for the existence of next_evolution, first.
if (allPokemon[x].next_evolution &&
allPokemon[x].next_evolution.includes(nameOfPokemon)) { ...

and find out which all pokemon have that name in their “next_evolution” field
That should make you think of filter. You want to filter the list of pokemon to find the matching ones.
But, as already pointed out, you need to be able to return false in your filter predicate if the pokemon you're testing does not have a next_evolution field. You can do that via testing, as suggested in another answer: pokemon.next_evolution && pokemon.next_evolution.includes..., or you can default it, as below: (pokemon.next_evolution || []).includes...
(Note though that both you original and that answer miss a step, which is to then collect that name properties from those next_evolution values.
So here is a simple function which should filter the list to find the correct items. To use it with a call to your API, I wrap it in a fetch call, and simply console.log the results. Obviously, you might well have other ways to call it.
const infoOfPokemon = (name, all) => all.filter(pokemon =>
(pokemon.next_evolution || []).map(p => p.name).includes(name)
)
fetch('https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json')
.then(resp => resp.json())
.then(allPokemon => console.log(
infoOfPokemon('Butterfree', allPokemon.pokemon) //~> [{Caterpie}, {Metpod}]
))

You cannot use includes function directly on array having objects instead of single object. It will give false as output.
For e.g:
var pets = [{'name':'cat'},{'name':'dog'},{'name':'bat'}];
console.log(pets.includes("cat")) //false
This results in false always.
Proper way is to use a map to get a particular object field on which you want to use includes function.
e.g:
var pets = [{'name':'cat'},{'name':'dog'},{'name':'bat'}];
console.log(pets.map((obj)=> obj.name).includes("cat")); //true
In Your case first see if allPokemon[x].next_evolution is undefined or not (i.e next_evolution key is present or not)
code becomes:
if (allPokemon[x].next_evolution &&
allPokemon[x].next_evolution.(obj)=> obj.name).includes(nameOfPokemon)) { ...

Related

Using equalTo() function in Firebase Database JavaScript v9

I am trying to use the equalTo function in the Firebase Database JavaScript v9 SDK. It's not very well documented like V8 is so can't figure out how to do what I want to do.
I want to filter results by the type field. My parent field is request-log with child elements like below.
{"backtrace":false,"message":false,"organisationID":"Empty","postData":false,"referrer":"Empty","remoteIP":"0.0.0.0","requestMethod":"POST","time":1630129562,"type":"Error","url":"Empty","user":{"email":"Empty","firstName":"George","id":37,"lastName":"Bates"},"userAgent":"Empty"}
I am trying the following, but not getting any results when loaded:
const readNewLogEntries = query(child(ref(db), 'request-log'), equalTo('Error', 'type'));
I have also tried this, as the reference docs say for the 2nd argument in the equalTo() function
This argument is only allowed if ordering by child, value, or priority.
But this isn't working either
const readNewLogEntries = query(child(ref(db), 'request-log'), orderByChild('type'), equalTo('Request', 'type'));
EDIT: Screenshot of DB
Remove the second parameter from equalTo().
The optional key argument can be used to further limit the range of the query. If it is specified, then children that have exactly the specified value must also have exactly the specified key as their key name. This can be used to filter result sets with many matches for the same value.
const getData = async () => {
const readNewLogEntries = await get(
query(ref(db, "request-log"), orderByChild("type"), equalTo("Request"))
// Filters where "type" is equal to "Request". Single arg here ⬆
);
console.log(readNewLogEntries.val())
return readNewLogEntries.val();
};
You can read more about the parameters in the documentation

Realm object list functions are undefined, even though object is defined and list is populated

Trying to push a new int into an int realm list. I can get the Realm object, I can print it and when I print the object it shows the list with it's content, I can use Realm Studio to edit, add numbers to the list, etc.. But when I try to call any methods form the list it says it is undefined.
Have tried async, await, then, though it was a synchronization issue, but doesn't seem like it.
The code below is similar to mine, but edited to hide the original names, etc, and does not have all the properties from the original, but it does not change the behave for the specific list I am trying to edit. Everything else works fine.
I have an schema like
let mySchema={
name:'MySchema',
properties:{
my_schema_id: 'string',
numbers: 'int[]'
}
The function to create a new object is
Realm.open({schema: [mySchema]})
.then(realm => {
realm.write(() => {
realm.create('MySchema', {my_schema_id: `${my_schema_id}`, numbers: [parseInt(number, 10)]});
});
I try to add a number with:
Realm.open({schema: [mySchema]})
.then((realm) => {
let fetchedSchema = realm.objects('MySchema').filtered(`my_schema_id ="${my_schema_id}"`);
console.log(fetchedSchema);
realm.write(()=>{
fetchedSchema.numbers.push(parseInt(number, 10));
});
And it gives an error:
(node:73249) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'length' of undefined
I expected to push the item to the list, or to be able to call the list functions. Instead, when I try to use the list it shows as undefined even though I can see it and it's content when I print the object...
Found a solution.
Querying let fetchedSchema = realm.objects('MySchema').filtered(my_schema_id ="${my_schema_id}"); actually returns an array of elements, so I just had to select the first with [0]at the end

Indexing into mongoose.model for an array is returning undefined

I've created a simple table (document?) in mongoDB.
I'm using Node and Mongoose to connect to it.
In my method, I am calling model.find({}) to retrieve all records and then iterating over them to find one that I want (this is within a loop - I'm thinking it will be more efficient to hit the DB once, and then process in memory to avoid connecting to the database each time).
When I console.log the match, I'm getting the full object printed out. When I print out one property, however, it's listing it as undefined. This property is an array, and it's happening for another property that has an array that I added as a test. What am I missing here?
Here's my code snippet:
Documents.find({}).then(docsData => { // Documents is my model
docs.entries.forEach(entry => { // docs.entries is the collection I want to match to
const match = docsData.find(
doc => doc['dropboxId'] == entry['id']
);
if (match) {
entry['tags'] = match.tags;
console.log('match tags', match.tags); // this prints out undefined
console.log('match', match); // this prints out the object with tags
}
Any ideas?
match is a Mongoose document which is different from normal JS object. I guess you need to do:
entry['tags'] = match.get('tags');

Javascript string/object/array confusion with JSON

I'm having a Laravel backend return some errors via Validator. These errors are passed through a HTTP response made by angular, and returned in JSON format.
The object is structured as seen below:
That name object has a value, which is the actual message that I'm after.
Currently, using loops etc., I can only get the name of the array (name) as a string...
I sometimes get multiple arrays within this error object, and I won't always know their names, so how may I retrieve that 0-index value in each of them, in a loop?
Thanks for any help.
Edit #1
Looping through it like this:
for(var err in res.data.errors){
console.log(Object.err[0][0]);
}
Gives me a Cannot get [0] index of undefined
How about this:
let errors = Object.values(response.data.errors);
// errors is now an array of arrays containing the validation errors
errors.forEach( (errorArray) => {
console.log(errorArray[0]);
} );
Another approach would be using Object.keys() instead of values. This is similar to what you already tried, where you get the name of the error property as a string, and then use it to access each error array:
let keys = Object.keys(response.data.errors);
keys.forEach( (errorKey) => {
console.log('error type', errorKey);
let errorArray = response.data.errors[errorKey];
console.log(errorArray[0]);
} );

Checking if an element exists in json

using the following feed:
http://api.twitter.com/1/statuses/user_timeline.json?screen_name=microsoft&include_rts=1&count=10
I am successfully able to loop through this to get the details I want to display on my html page.
However, I need to check if retweeted_status.user.profile_image_url exists, and I am not sure how to do that?
Currently I am looping through the data where data is returned by jquery-ajax:
data[i].retweeted_status.user.profile_image_url
if data[i].retweeted_status.user.profile_image_url does not exist, it does not return null or undefined, I just get the following error:
cannot read property 'user' of undefined
That error message suggests that either your data[i] or your retweeted_status is undefined, which means your call to get the json is most likely failing. WHen data is returned from Twitter it will aways have a profile image url, because they show an egg-like image for those with none uploaded. You should put this before your for loop:
if (typeof(retweeted_status) != "undefined")
{
//code for what to do with json here
}
I think it's a good answer:
if('key' in myObj)
if (something !== undefined) {
...
}
... or even better:
if (typeof something != "undefined") {
...
}
If you are looping and accessing nesting objects:
if(!data)
return;
while(data.length)
{
var tweet_data = data.shift();
/* do some work */
if(!tweet_data|| !tweet_data.retweeted_status)
continue;
var retweeted_status = tweet_data.retweeted_status;
/* do your other work */
}
This loop no longer needs to use array indexes, which isn't the most efficient unless you specifically need the index for something. Instead, it pops the first element off the array and using that object directly. The loop internals can then check the existence of a property on tweet_data.
I try to avoid using more than 1 level of dereferencing for 2 reasons (like objA.child.property):
1) You can check the existence of an object from the start and if it doesn't exist, jump out or assign default values.
2) Everytime JavaScript needs to access the method property, it first has to find child withing objA and then access property. Could be slow in large loops.
Take a look at $.grep(). It helps you loop through JSON objects. I used it on the link you provided. I used it to loop through the tweets and find the retweeted user images. You can have a look at my code here:
http://jsfiddle.net/q5sqU/7/
Another thing you can do, which has worked for me:
if(retweeted_status) {
// your code
}

Categories

Resources