#how to extract a value from a key:value pair inside of an object that's inside of an array
145 messages · Page 1 of 1 (latest)
- Consider reading #how-to-get-help to improve your question!
- Explain what exactly your issue is.
- Post the full error stack trace, not just the top part!
- Show your code!
- Issue solved? Press the button!
Sounds like you're looking for map() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
What?
I haven't found how to extract a value from an object there though
You pass a function to the map method to return a new array of what you need
const results = []; // the array of objects in question
const newArr = results.map((strike) => strike.guard_username); // newArr is now string[]
console.log(newArr); // ['AstroHWeston','AstroHWeston',...]
Okay, I got that down, but a user can have multiple strikes so I need to extract it from multiple objects, how can i do that then
Documentation suggestion for @novel wing:
Array.prototype.filter()
The filter() method of Array instances creates a shallow copy of a portion of a given array, filtered down to just the elements from the given array that pass the test implemented by the provided function.
check if it‘s the right user using filter
then map the resulting array
more importantly though, you‘re running a database query, so if you‘re only interested in specific results, then you should modify your query to do that for you
im doing a querry on a username in a strikes datbase, a user can have multiple strikes which basically means it can return multiple results
and where’s the problem? I‘m having trouble understanding what you‘re stuck on
what‘s the end result you want to get from the array of objects
basically, each object is a row in a database extract, meaning the key is a column and the value is the value of that column,
I need to extract a specific value from a specific column from all the objects, then put each single result on an embed, along with it's ID (which is another column in the database)
but i also need to reply with a specific message if the array is empty (aka, if the user has no strikes)
and why is a map not the solution for this? you have an array of object that you need to transform into an array of embeds based on each value
if you want to create one embedBuilder and append for each row of the array, there‘s also .reduce(), but I don‘t think that‘s even necessary in this case
right but this doesn't return an array when i log it, it just logs a string
because that‘s how an array is stringified
ah i see
Array.isArray(variable) can also show if it‘s an array
yeah i know that but
it‘s general fuckery because console.log() is not the same as array.toString()
console.log() calls a formatting function
okay wait let me go back one step though
let's say the querry returns an empty array, meaning there is nothing in the database, how would i handle that then? like i tried doing this but it didn't work
if (result === []) {
//code here
} else {
//code here
}
and it actually went into the else part and not the if part and i have no idea why
triple equality will always fail that.
That's because objects are compared using reference, not some deep equality.
const obj1 = {test: '1'}; // new reference
const obj2 = {test: '1'}; // new reference
console.log(obj1 === obj2) // False
Use result.length === 0 instead
i console.logged the result before that and it logged []
essentially you're logging whether or not result and the newly created [] are stored at the same memory address, which is never possible
ohhh okay that makes sense
one sec
What did you mean here?
I wouldn‘t worry about it. Some less readable way to accomplish what you‘re going for
okay let me get back on track now
okay, im sorry if im annoying you lmao, but what if i wanted to get the number of how many results there are, in my case, how many objects technically (because each object is a strike)
cause i would be sending out how many strikes a specific person has
the length property of the array …
oh does each object count as 1?
if so then that's simpler than i thought lmfao
out of curiosity, is javascript your first programming language?
sort of yeah, why
discord.js is pretty complex for a starter project
it's not really my first project though
plus im kind of forced to learn like 4 programming languages at once so lmfao 😭
well, the length of an array exists in almost every programming language
so that's why I suspected it
ah i see what you mean
wait can i just do arrName[objNumber].keyName
i always
tried to avoid fiddling around with complex array operations but
yeah, remember that [index] is 0-indexed though
yes i know that
okay hold on let me try something
okay, say someone had three strikes, and someone else only 1, would it be possible to show all of them as an embed description (not fields) using the same embed?
or actually i might just use fields
well, the description accepts one long string, so you can concatenate each object to a string variable
i mean what if i wanted to use .setFields or .addFields in order to add the amount of fields that there are strikes for that user?
this is purely me brainstorming but couldnt i make a for loop to make it add fields to the embed until it's at the last array index?
yeah? addFields also accepts an array of embed fields
result array -> .map() to APIEmbedField {name: string, value: string, inline?: boolean} -> pass it to EmbedBuilder.addFields()
isn't it value, not description
my bad, value*
or is this something else
right
i'm having a bit of trouble understanding this
you should google keywords you don't understand. You must be able to immediately know what these terms mean if you want to build a discord bot
this is also mentioned in rule 3 of this discord
https://discord.js.org/docs/packages/discord.js/main don't forget the discordjs docs and
https://developer.mozilla.org/en-US/ mdn docs
i just
don't know what APIEmbedField is supposed to mean
im looking at the guide rn
It's a type that describes an embed field that the discord API accepts. {name: string, value: string, inline?: boolean}
yeah but doesn't addFields require you to put in the amount of objects that you want the fields? some people might have more and some might have less it's not a static number
i can explain more if you misunderstood because i might've not explained it the best 😅
there's the upper limit of 25 due to how discord set that limit, but there's no limit for passing fields to the function
it uses rest parameters / spread operator
yeah but if i set the title as an index from an array, which index doesn't exist, wouldn't that error and crash?
like if i added 5 fields and someone only had 2 strikes for example
no, because if you followed that pipeline I explained above that is impossible
map() applies the function to each element, which can't go out of bounds
passing the array to .addFields() uses the content within, but can't go out of bounds
if you loop over an array and are out of bounds, then you wrote your for loop wrong.
oh yeah about that pipeline
oh wait im supposed to be using a for loop
i moved it far out of the way lmfao one sec
this doesn't use a for loop.
oh
okay wait so i got this far
const yesStrikes = new EmbedBuilder()
.setTitle(`${result.length} strikes found for ${guardNickname}`)
.setColor('#17d058')
//result.map().to
const newID = result.map((id) => id.strike_id);
const newReason = result.map((strike) => strike.strike_reason);
I think you misunderstand what map does.
const newArray = [];
for (let i = 0; i < result.length; i++) {
const id = result[i];
newArray.push(id.strike_id);
}
is the same as
const newArray = result.map((id) => id.strike_id);
it can transform to ANY value. The function in map receives a strike object as parameter, and whatever you return ends up in the new array
that includes transforming the strike object into an APIEmbedField
If that confuses you, then I suggest looking up the following concepts
- General: Callback Function
- JavaScript: Arrow Function Syntax
so basically .map just executes a function on every single element in an array
correct!
meaning for me to add fields to an embed
it would add a new field
for every element in an array?
map is specifically meant for returning the function's value
it returns an array that has the same length as result, but each element within was changed according to the passed function
in this case, it's function(id) { return id.strike_id; }
right so i need
ok so basically
what you're telling me i need to do is
since an object is a single element in an array
i need the function to extract the strike_id value from each object in an array, and then store it in a separate array
?
you need to take each strike object and change it into an APIEmbedField. Then you can return that newly created object
since you now have an array of APIEmbedField, you can pass it to EmbedBuilder.addFields()
hmm wait i have an idea
so if i did
const newID = result.map((id) => id.strike_id);
that would return.. an object?
it would return a string
since strike_id is a string
yeah but i did console.log(typeof newID) and that
logged objewct
oh that
it‘s an array of strings
arrays are objects in javascript so typeof logged that
ohhh
okay
OH okay i was
thinking of something else
okay well then cant i just make a for loop for .addField and it would repeat as much times as there are elements in either one of the arrays
so
const newID = result.map((id) => id.strike_id);
const newReason = result.map((strike) => strike.strike_reason);
for (let i = 0; i <= newID.length; i++) {
yesStrikes.addFields(
{title: `${newReason[i]}`, value: `${newID[i]}`}
)
}
you can. There‘s always multiple ways
ah
that code will fail though since i = newID.length is out of bounds
remember, 0 indexed. So i goes from 0 to newID.length - 1
oh so
is it because i put <= instead of <
yes
uhh that still crashes
OHH WAIT
i set it to title: not name:
i think
oh okay that fixed it, thank you so much for the time <3
I'll keep this open just in case I need something
I'll close it later today
@tall jasper hey sorry for the ping but i have another question, i added a new column to the database which is date_issued which just stores a UNIX timestamp of when the command was ran.
Now when I try to print out those times on an embed using the same maping method as we described before, but it prints out the two values that are in the database for both cases, why is that?
const newID = result.map((id) => id.strike_id);
const newReason = result.map((strike) => strike.strike_reason);
const newTime = result.map((time) => time.date_issued)
for (let i = 0; i < newID.length; i++) {
yesStrikes.addFields(
{ name: `${newReason[i]}`, value: `Strike ID: ${newID[i]} | <t:${newTime}>` }
)
}
Sorry for the ping btw
never the fuck mind im blind as fuck
i swear to god i ask for help and as soon as i do it clicks
get a rubber duck so you can ask it first
if it clicks immediately, it‘ll work