How to implement a search function for array of classes - arrays

I have a User class as follows:
class User
attr_reader :username, :password
def inintialize(username, password)
#username = username
#password = password
end
end
And I want to store many of these User classes in an array as follows:
users = []
def initialize_users
user = User.new("user0", "password0")
users.push(user)
user = User.new("user1", "password1")
users.push(user)
end
And now I want to implement a searching function where I can search via username, or password. I know I can iterate over the classes comparing each field like so:
def search(username)
users.each do |user|
if user.username == username then
puts "Found"
break
end
end
end
But is there any other way to do this without the iterating or is this simply the easiest/cleanest way?
I was thinking maybe there is a way to do something like:
users["username_to_find"]
=> true
Although I am not sure how to implement that. I would believe I would have to rewrite the User class to have a built in list, but from there I am lost. I guess even if I do implement this feature there is still a iteration that has to happen.
Also I would like to access that users data from within that notation such as
users["username_to_find"].password
=> "password111"
Anyone have any ideas?
PS: User class is reduced to relevant code, it actually holds many more data members which are specific to each user such as sockets, and methods for sending data to a specific users sockets.

You really have no choice but to iterate over every element of the array and perform your matching test. Enumberable#detect is what you would want to use:
def search(username)
# return the first matching result
users.detect { |user| user.username == username }
end
This would return the first User with a matching username or nil. If you want to allow multiple results to be returned (e.g. more of what the word "search" denotes) than you would want to use Enumberable#select which returns all matching blocks:
def search(username)
# return ALL matching results
users.select { |user| user.username == username }
end
If you need to potentially match on multiple criteria (e.g. search on username and first name, etc) than you will need to take this approach. If you are only searching on username, than the solution given by #dax above is perfect.

If it doesn't need to be an Array, why not use a Hash? It provides exactly the functionality you want.
users = {}
user = User.new("user0", "password0")
users[user.username] = user
Access it like so
users['tim_the_toolman'] # => nil, there is no user by that name
users['user0'] # => returns user0
users['user0'].password # => 'password0'

use Array find and select methods. Assume you are searching by name
find returns first object which satisfies your condition
array.find { |user| user.name == searched_name } # will be either one User or nil, if neither has name eq to searched_name
select returns all objects which satisfy your condition
array.select { |user| user.name == searched_name } #will be either array of Users which have name eq searched_name or an empty array when none has this name

Related

Alternative Ways to Define Users in Discord.JS

So to define users for things like displaying avatars, etc. i've been using this;
var user = message.mentions.users.first() || message.author;
But i've been trying to figure out how people have been able to define users without mentions. Example - my command requires me to tag someone whereas Dyno can do it with partial names. Any tips would be great, thanks!
An easy way to do so would probably be using the .find() function, where you can search for a certain object based on a method.
For example, if we were to have an args variable in our callback (Very easy to do so using a proper command handler - I'd suggest looking for tutorials if you aren't familiar with command handlers), and we were to ask a user to pass in a member's name, we could very easily get the user object using:
const user = message.guild.users.cache.find(user => user.username === args[0]);
// Keep in mind, 'user' is just a variable I've defined. It could also be 'monke => monke.username' if you wish.
Or, if we were to ask for their ID, we could use the .get() function to get the user object by ID:
const user = message.guild.users.cache.get(args[0]);
Do keep in mind it's not the greatest to have these kinds of object getting functions, as there are always multiple conflicts that could occur whilst getting the object, such as if there are multiple users with the same name/tag. I'd highly recommend sticking to your mention-based user objects, as it's the most accurate and non-conflicting method.
Every guild has a list of members which you can search through by enabling the Server Members Intent for your bot via the Discord Developer Portal. Once you have done that, you can fetch a collection of all members of a guild by doing
guild.members.cache;
You can then search this collection to find a member based on a search query using .includes(), .filter() or something similar. For example:
let query = "something";
let list = guild.members.cache.filter(member => member.user.username.includes(query));
console.log(Object.entries(list));
// expected output: list of all server members who's usernames contain "something"
You could also use the .find() method (since a collection is a map) to return a member with an exact username:
let member = guild.members.cache.find(member => member.user.username === query);
console.log(member.tag);
// expected output: tag of the user who's username is "something"
This is as simple as that:
var user = message.guild.members.cache.find(u => u.user.username.toUpperCase() === args.join(" ") || u.user.username.toLowerCase() === args.join(" ") || u.user.username === args.join(" "))
This will find the user on the current guild but you can also search your bot for this user by doing:
var user = client.users.cache.find(u => u.username.toUpperCase() === args.join(" ") || u.username.toLowerCase() === args.join(" ") || u.username === args.join(" "))
I have to assume that you already defined args and client. The example above will find users just by typing their name. toUpperCase means if you type the username in uppercase letters it will find the users anyways. toLowerCase means if you type the username in lowercase letters it will find the user as well. And you could also just type the username as it is. || means or so you can decide how you write the username, it will be found anyways.

Extracting an array of values from an array of hashes in Puppet

I have the following array of hashes in hiera:
corporate_roles:
- name: 'user.1'
system_administrator: true
global_administrator: false
password: TestPassword1234
- name: 'user.2'
system_administrator: true
global_administrator: true
password: TestPassword1234
I need to extract a list of users with a give role (eg global_administrator) to be assigned later on.
I managed to use the map function to extract the data I need:
$corporate_roles = lookup('corporate_roles')
$global_admins = $corporate_roles.map | $hash | { if ($hash['global']){$hash['name']}}
notify { "global admins are: ${global_admins}":
}
However this results in undef values seemingly making their way into the array for the users that don't match the criteria:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [, user.2]]/message: defined 'message' as 'global admins are: [, user.2]'
Notice: Applied catalog in 0.04 seconds
I can get around this by using the filter function as such:
$test = $global_admins.filter | $users | {$users =~ NotUndef}
Which results in clean output:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [user.2]]/message: defined 'message' as 'global admins are: [user.2]'
Notice: Applied catalog in 0.03 seconds
But I suspect there must be a better way of doing this and I am either missing some logic in my map or I am likely using the wrong function altogether for this.
I would like to know if there is a better way to achieve what I am trying to do?
But I suspect there must be a better way of doing this and I am either
missing some logic in my map or I am likely using the wrong function
altogether for this.
map() emits exactly one output item for each input item, so if your objective is to apply a single function to obtain your wanted output from your (lengthier) input, then indeed, map will not achieve that.
I would like to know if there is a better way to achieve what I am trying to do?
Personally, I would do the job by filtering out the hashes you want from your input and then mapping those to the wanted output form (as opposed to mapping and then filtering the result):
$global_admins = $corporate_roles.filter |$hash| {
$hash['global_administrator']
}.map |$hash| { $hash['name'] }
I like that because it's nice and clear, but if you want to do it with one function call instead of two then you're probably looking for reduce:
$global_admins = $corporate_roles.reduce([]) |$admins, $hash| {
$hash['global_admin'] ? {
true => $admins << $hash['name'],
default => $admins
}
}

How to choose one field from one retrieved row in CakePHP?

$users = TableRegistry::get('Users');
if ($this->request->data) {
$query = $users->findByEmail($this->request->getData('email'));
In the code above, I have retrieved one row from my table where the user's email matches the requested email.
Next, I want to write the code below to check if the password of the selected user is same as the requested password.
PasswordOfSelectedRow == md5($this->request->getData('password')))
What should I put instead of PasswordOfSelectedRow?
The following line returns a query object from a dynamic finder
$query = $users->findByEmail($this->request->getData('email'));
From the docs:
Once you have a query object from a dynamic finder, you’ll need to call first() if you want the first result.
So you could write something like this to retrieve the user:
$user = $query->first();
And then to compare to the request data:
$user->password == md5($this->request->getData('password')))

How to add items to an array one by one in groovy language

I´m developing a grails app, and I already have a domain class "ExtendedUser" wich has info about users like: "name", "bio", "birthDate". Now I´m planning to do statistics about user´s age so I have created another controller "StatisticsController" and the idea is to store all the birthDates in a local array so I can manage multiple calculations with it
class StatisticsController {
// #Secured(["ROLE_COMPANY"])
def teststat(){
def user = ExtendedUser.findAll() //A list with all of the users
def emptyList = [] //AN empty list to store all the birthdates
def k = 0
while (k<=user.size()){
emptyList.add(user[k].birthDate) //Add a new birthdate to the emptyList (The Error)
k++
}
[age: user]
}
}
When I test, it shows me this error message: Cannot get property 'birthDate' on null object
So my question is how is the best way to store all the birthdates in an single array or list, so I can make calculations with it. Thank you
I prefer to .each() in groovy as much as possible. Read about groovy looping here.
For this try something like:
user.each() {
emptylist.push(it.birthdate) //'it' is the name of the default iterator created by the .each()
}
I don't have a grails environment set up on this computer so that is right off the top of my head without being tested but give it a shot.
I would use this approach:
def birthDates = ExtendedUser.findAll().collect { it.birthDate }
The collect method transforms each element of the collection and returns the transformed collection. In this case, users are being transformed into their birth dates.
Can you try:
List dates = ExtendedUser.findAll().birthDate

Use a db.StringProperty() as unique identifier in Google App Engine

I just have a hunch about this. But if feels like I'm doing it the wrong way. What I want to do is to have a db.StringProperty() as a unique identifier. I have a simple db.Model, with property name and file. If I add another entry with the same "name" as one already in the db.Model I want to update this.
As of know I look it up with:
template = Templates.all().filter('name = ', name)
Check if it's one entry already:
if template.count() > 0:
Then add it or update it. But from what I've read .count() is every expensive in CPU usage.
Is there away to set the "name" property to be unique and the datastore will automatic update it or another better way to do this?
..fredrik
You can't make a property unique in the App Engine datastore. What you can do instead is to specify a key name for your model, which is guaranteed to be unique - see the docs for details.
I was having the same problem and came up with the following answer as the simplest one :
class Car(db.Model):
name = db.StringProperty(required=True)
def __init__(self,*args, **kwargs):
super(Car, self).__init__(*args, **kwargs)
loadingAnExistingCar = ("key" in kwargs.keys() or "key_name" in kwargs.keys())
if not loadingAnExistingCar:
self.__makeSureTheCarsNameIsUnique(kwargs['name'])
def __makeSureTheCarsNameIsUnique(self, name):
existingCarWithTheSameName = Car.GetByName(name)
if existingCarWithTheSameName:
raise UniqueConstraintValidationException("Car should be unique by name")
#staticmethod
def GetByName(name):
return Car.all().filter("name", name).get()
It's important to not that I first check if we are loading an existing entity first.
For the complete solution : http://nicholaslemay.blogspot.com/2010/07/app-engine-unique-constraint.html
You can just try to get your entity and edit it, and if not found create a new one:
template = Templates.gql('WHERE name = :1', name)
if template is None:
template = Templates()
# do your thing to set the entity's properties
template.put()
That way it will insert a new entry when it wasn't found, and if it was found it will update the existing entry with the changes you made (see documentation here).
An alternative solution is to create a model to store the unique values, and store it transationally using a combination of Model.property_name.value as key. Only if that value is created you save your actual model. This solution is described (with code) here:
http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/
I agree with Nick. But, if you do ever want to check for model/entity existence based on a property, the get() method is handy:
template = Templates.all().filter('name = ', name).get()
if template is None:
# doesn't exist
else:
# exists
I wrote some code to do this. The idea for it is to be pretty easy to use. So you can do this:
if register_property_value('User', 'username', 'sexy_bbw_vixen'):
return 'Successfully registered sexy_bbw_vixen as your username!'
else:
return 'The username sexy_bbw_vixen is already in use.'
This is the code. There are a lot of comments, but its actually only a few lines:
# This entity type is a registry. It doesn't hold any data, but
# each entity is keyed to an Entity_type-Property_name-Property-value
# this allows for a transaction to 'register' a property value. It returns
# 'False' if the property value is already in use, and thus cannot be used
# again. Or 'True' if the property value was not in use and was successfully
# 'registered'
class M_Property_Value_Register(db.Expando):
pass
# This is the transaction. It returns 'False' if the value is already
# in use, or 'True' if the property value was successfully registered.
def _register_property_value_txn(in_key_name):
entity = M_Property_Value_Register.get_by_key_name(in_key_name)
if entity is not None:
return False
entity = M_Property_Value_Register(key_name=in_key_name)
entity.put()
return True
# This is the function that is called by your code, it constructs a key value
# from your Model-Property-Property-value trio and then runs a transaction
# that attempts to register the new property value. It returns 'True' if the
# value was successfully registered. Or 'False' if the value was already in use.
def register_property_value(model_name, property_name, property_value):
key_name = model_name + '_' + property_name + '_' + property_value
return db.run_in_transaction(_register_property_value_txn, key_name )

Resources