Given user string input, how to check if object is in array - javascript

I'm trying to build a reference bot for discord that can be used to look up information (in this case, cars) and I'm having trouble with a concept. The user is capable of running a command to look up car information. The command the user gives might be $car1, and car1 will be stored in the variable inputCar. The array validCars holds all of the cars that can be looked up, and car1 is one of them. car1 is clearly not a string in this case but an object with multiple fields, but I need to figure out how to be able to look up information on the cars given a string input from the user. My question is twofold:
1) I know that the outer if statement won't work because inputCar is a string that the user entered, and the objects in the validCars array are objects. How can I properly check if what the user enters (in string format) matches the name of one of the objects?
2) Now assuming I can actually determine if the car exists in validCars given the user input, how can I access the fields (name, model, color) given the user input in order to print them?
This might not be the best way to accomplish what I'm trying to do, so any suggestions are appreciated.
var validCars = [car1, car2, car3, car4];
var car1 = {
name:"Corvette Stringray",
model:"2018",
color:"red"
};
/***
*** car2, car3, and car4 all have the same setup as car1, just different values.
***/
// Scan each message (client.on is discord.js jargon)
client.on("message", (message) => {
// Potential car name entered by user (message.content is discord.js jargon,
//it is just returning the string the user entered without the leading command prefix).
// e.g. the value in inputCar might be "car1" if the user wanted to see info on car1.
var inputCar = message.content.substr(1);
// SHOULD check if this is an actual car. This if statement won't work because inputCar is a string,
// and the values in validCars are not strings but objects.
if (validCars.includes(inputCar) == true)
{
// Condition when car1 is entered (there would be other cases for the other cars)
if (message.content == config.prefix + "car1")
{
// Print car1 info including name, model, and color
}
}
else
{
// Invalid car was entered by user.
}
});

You might want to store the cars id with the car in a Map:
const carByKey = new Map([
["car1", car1],
/*...*/
]);
Then its quite easy to get the car:
if(carByKey.has(message)){
const car = carByKey.get(message);
console.log(car.name);
//...
}
If you really want to get the javascripts variable that has the same name and is in global scope, thats possible with window/global (depending on your environment):
if(message in window){
const car = window[message];
}
....But thats a very very bad idea.

Related

How to use RegEx to find strings deep inside an array of objects

I'm currently trying to find a way to match user input to find a user in Discord, for commands that we didn't necessarily want tagging the user. As it is, the method I'm using to get that username is
var member = message.guild.members.find('nickname', `${searched}`);
However this only pulls the name if it's an exact match, which is kind of annoying.
How would I go about pulling a name with only a partial bit of it?
For further clarification, the variable 'searched' is what I'm looking to replace in order to match the string provided by user input to the nickname attribute in Discord's members objects.
EDIT
Found what I was looking for
var member = message.guild.members.find(element => element.nickname.includes(searched) == true);
This should work if members is an array. It should match nickname anywhere in the string.
const nickRegx = new RegExp('nickname')
var member = message.guild.members.find((member => nickRegx.test(member));
Found the answer to my own question after an hour or so
var member = message.guild.members.find(element => element.nickname.includes(searched) == true);

Firebase JavaScript Child Comparison

I need to compare some values in my Firebase Database using JavaScript, but I'm having a hard time doing that. See image above.
The way that is suppose to work is I need to check if the user likes the same id as the other user. So for example:
User XbsX0IskrHVcaEmEBgyeok9isiM2 liked 4 items with unique ID's. Now I need to check if user jBc2Ls32DgMUSgzKUkVSw38UjQD2 liked the same thing to see if it's a match.
I have this code:
var check = ref.child('likes').child(uid2).child(uid2);
but it's not working.
You could iterate over the likes of the first user and make sure that everyone exists on the list of likes of the second user:
// Gets the list of likes from both users
var likes_user_1 = ref.child('likes').child(uid1);
var likes_user_2 = ref.child('likes').child(uid2);
// Iterates over the list of likes of the first user
var isAMatch = Object.keys(likes_user_1).every(function(like) {
// Returns true if user_2 has this like
return likes_user_2[like];
});

meteor.js & mongoDB - query with multiple fields

CONTEXT
I am trying to create a search functionality allowing users to fill in multiple fields, submit, and see a list of matching items from one collection. I do this using a form on the front end, which updates session variables on back-end, which are then passed as query to a mongodb collection.
HOW IT SHOULD WORK
If a user submits a venue size, then venues of that size are shown. If only a location is typed in, then venues within that location are shown. If both a size and a location are submitted, then venues that match both criteria are shown.
HOW IT ACTUALLY WORKS
If nothing is filled in, pressing search yields all items in the collection. Submitting both location and size yields venues that match both criteria. However, filling in only one field and leaving the other empty yields nothing in results. I'm wondering why this might be - it's almost as if the query is searching for a field that literally contains ''... but then why don't I see this behavior when leaving both fields empty? Help much appreciated!
CODE SNIPPET
//Search Form Helper
Template.managevenues.helpers({
venue: function () {
var venueNameVar = Session.get('venueNameVar');
var venueLocationVar = Session.get('venueLocationVar');
if(venueNameVar || venueLocationVar){
console.log(venueNameVar);
console.log(venueLocationVar);
return Venues.find({
venueName: venueNameVar,
'venueAddress.neighbourhood': venueLocationVar
});
} else {
return Venues.find({});
}
});
The answer lies in your query
Venues.find({
venueName: venueNameVar,
'venueAddress.neighbourhood': venueLocationVar
});
If you don't have one of your vars set it will look like this...
{
venueName: undefined,
'venueAddress.neighbourhood':'someVal'
}
So it would match any venue that doesn't have a name and is in some neighborhood.
A better approach would be to only set query criteria if there's a value to search...
var query = {};
if(Session.get('venueNameVar')) {
query.venueName = Session.get('venueNameVar');
}
if(Session.get('venueLocationVar') {
query.venueAddress = {
neighbourhood : Session.get('venueLocationVar');
}
}
return Venues.find(query);
I think this will work a bit better for you!

Adding/updating data to Parse.com using Javascript

When using Parse, if I have an object called people and two columns, one called name and another called age. The user can input a name to match one that is already stored in Parse, and also input an age to be added to that specific name. How can I get it to search for the name the user has inputted, and if the name matches the user's input, add the age to that specific name?
You cannot save anything in an object unless you have access to its objectId, therefore you need to perform a search as well as a save. You need to find the object(s) associated with the name the user enters and then add age value and save it. The code becomes something like:
var query = new Parse.Query("people");
query.equalTo("name", inputName);
query.find().then( function(objects) { // query and search for object(s)
var person = objects[0]; // get the first object, there can be more than one obviously
person.set("age", inputAge); // set the age
return person.save(); // save the age value in object
}).then(function() {
// success
}, function(error) {
// error
});

Dealing with a JSON object too big to fit into memory

I have a dump of a Firebase database representing our Users table stored in JSON. I want to run some data analysis on it but the issue is that it's too big to load into memory completely and manipulate with pure JavaScript (or _ and similar libraries).
Up until now I've been using the JSONStream package to deal with my data in bite-sized chunks (it calls a callback once for each user in the JSON dump).
I've now hit a roadblock though because I want to filter my user ids based on their value. The "questions" I'm trying to answer are of the form "Which users x" whereas previously I was just asking "How many users x" and didn't need to know who they were.
The data format is like this:
{
users: {
123: {
foo: 4
},
567: {
foo: 8
}
}
}
What I want to do is essentially get the user ID (123 or 567 in the above) based on the value of foo. Now, if this were a small list it would be trivial to use something like _.each to iterate over the keys and values and extract the keys I want.
Unfortunately, since it doesn't fit into memory that doesn't work. With JSONStream I can iterate over it by using var parser = JSONStream.parse('users.*'); and piping it into a function that deals with it like this:
var stream = fs.createReadStream('my.json');
stream.pipe(parser);
parser.on('data', function(user) {
// user is equal to { foo: bar } here
// so it is trivial to do my filter
// but I don't know which user ID owns the data
});
But the problem is that I don't have access to the key representing the star wildcard that I passed into JSONStream.parse. In other words, I don't know if { foo: bar} represents user 123 or user 567.
The question is twofold:
How can I get the current path from within my callback?
Is there a better way to be dealing with this JSON data that is too big to fit into memory?
I went ahead and edited JSONStream to add this functionality.
If anyone runs across this and wants to patch it similarly, you can replace line 83 which was previously
stream.queue(this.value[this.key])
with this:
var ret = {};
ret[this.key] = this.value[this.key];
stream.queue(ret);
In the code sample from the original question, rather than user being equal to { foo: bar } in the callback it will now be { uid: { foo: bar } }
Since this is a breaking change I didn't submit a pull request back to the original project but I did leave it in the issues in case they want to add a flag or option for this in the future.

Categories