Python - Querying dictionaries within dictionaries - python-3.x

I have a question if anyone would be so kind to help me? :) Could you help me with a little bit of code regarding dictionaries within dictionaries:
A simple program that prompts a user for an email address (that must be stored in the database) in order to gain access to the webpage
Here we shall build dictionaries to hold the data... within a dictionary that will hold the entire database:
database_of_users = {
"Cleaus": {"email" : "c#gmail.com"},
"Jay" : {"email" : "j#hotmail.com"},
"Tremaine" : {"email" : "t#gmail.com"},
"Kyla" : {"email" : "k#outlook.com"}
}
Next bit:
user_email = input("To gain access to this feed, you must be a member
of the site. \n\nIf you are already a member, please enter your
email address below: \n\n").strip().lower()
Then:
while True:
if "#gmail.com" in user_email or "#hotmail.com" in user_email or
"#outlook.com" in user_email:
break
elif "#gmail.com" not in user_email or "#hotmail.com" not in
user_email or "#outlook.com" not in user_email:
user_email = input("\nPlease enter a valid email
address (gmail/hotmail/outlook): \n\n").strip().lower()
Here I am stuck on how to search all of the secondary (nested) dictionary value entries within the main dictionary. I have tried turning it into a list first and then calling what I thought would be the value entries in the second dictionary to query them, but it is not working:
database_aslist = list(database_of_users.values()
I realise the if statement below is just calling the first bit before the 'item' = (key:value), so in this case the name "Cleaus", "Jay","Tremaine","Kyla", but I am just unsure of how to query all data within the main dictionary completely, keys and values included, at the same time? Is it possible?
if user_email in database_of_users:
print("\nOk, I have found you. Please enjoy the show!")
print("\n\n[GAINED ENTRY]")
if user_email not in database_of_users:
print("\nSorry, that email address does not seem to be in our database.
To gain access, please register for one of our packages here:
\n\n[LINK WHERE THEY CAN SIGN UP]\n\nThank you!\n")
Thanking you all in advance for your help!

I've never known a way without walking through the dictionary. Something like this:
user_found=False
for user in database_of_users:
if database_of_users[user]["email"]==user_email:
user_found=True
break
if user_found:
print("\nOk, I have found you. Please enjoy the show!")
print("\n\n[GAINED ENTRY]")
else:
print("\nSorry, that email address does not seem to be in our database.
To gain access, please register for one of our packages here:
\n\n[LINK WHERE THEY CAN SIGN UP]\n\nThank you!\n")
Though, if email is what is being entered, changing the database_of_users to use emails in the first nesting might be the easier way to go if that's an option:
database_of_users={
"c#gmail.com": {"name":"Cleaus"},
"j#hotmail.com": {"name":"Jay"},
...
}

Related

Terraform variable user inputs long key value pair

I am using a 3rd party app called Morpheus (not a fan of it but its enforced)
I built some modules which are easy enough to request the end user selecting a "Catalog item" to be provisioned and asked for name, and drop down list with ex: instance size, etc.
My issue is thou, I need the user to enter in 1 long string of key value pair to be added to an attribute.
for example
parameters = [var.params]
and the end user inputs in the text field
"example1": "value1", "example2": "value2"
but of course this does not work. I tried {"example1": "value1", "example2": "value2"} and
parameters = [jsondecode(var.params)]
also does not work. Stuck on what / how to request end user to enter in the values in a specific format. The txt box is 1 liner btw :(, hence why im not a fan of morpheus but whatev's

loc not functioning correctly in pandas

I have a Dataframe, which has a bunch of ID name pairs in it. I create it by doing the following:
market_df = pd.DataFrame(markets_info['markets'])
market_df.astype(dict(id=int, name=str))
I received ID numbers from a process and I need to grab the associated name to that ID. I have tried creating an index on the ID and then parsing it, but that doesn't seem to set the ID correctly.
I now am trying to do the following: exch_name = MARKET_IDS.loc[MARKET_IDS['id'] == exchange_id, 'name']
I have verified that exchange_id is also of type int.
What am I missing here?
I don't know if this is because you left out some crucial information from this, but from what it sounds like in your post you're not really altering market_df at all, as your second line is not an assignment. It should read market_df = market_df.astype(dict(id=int, name=str))

Getting index of the resultset

Is there a way to get the index of the results within an aql query?
Something like
FOR user IN Users sort user.age DESC RETURN {id:user._id, order:{index?}}
If you want to enumerate the result set and store these numbers in an attribute order, then this is possible with the following AQL query:
LET sorted_ids = (
FOR user IN Users
SORT user.age DESC
RETURN user._key
)
FOR i IN 0..LENGTH(sorted_ids)-1
UPDATE sorted_ids[i] WITH { order: i+1 } IN Users
RETURN NEW
A subquery is used to sort users by age and return an array of document keys. Then a loop over a numeric range from the first to the last index of the that array is used to iterate over its elements, which gives you the desired order value (minus 1) as variable i. The current array element is a document key, which is used to update the user document with an order attribute.
Above query can be useful for a one-off computation of an order attribute. If your data changes a lot, then it will quickly become stale however, and you may want to move this to the client-side.
For a related discussion see AQL: Counter / enumerator
If I understand your question correctly - and feel free to correct me, this is what you're looking for:
FOR user IN Users
SORT user.age DESC
RETURN {
id: user._id,
order: user._key
}
The _key is the primary key in ArangoDB.
If however, you're looking for example data entered (in chronological order) then you will have to have to set the key on your inserts and/or create a date / time object and filter using that.
Edit:
Upon doing some research, I believe this link might be of use to you for AI the keys: https://www.arangodb.com/2013/03/auto-increment-values-in-arangodb/

Cloudant 1 to many function

I’ve just started to use Cloudant and I just can’t get my head around the map functions. I’ve been fiddling with the data below but it isn’t working out as I expected.
The relationship is, a user can have many vehicles. A vehicle belongs to 1 user. The vehicle ‘userId’ is the key of the user. There is a bit of redundancy as in user the _id and userId is the same, guess later is not required.
Anyhow, how can I find for a/every user, the vehicles which belong to it? The closest I’ve come through trial and error is a result which displays the owner of every vehicle, but I would like it the other way round, the user and the vehicles belonging to it. All the examples I’ve found use another document which ‘joins’ two or more documents, but I don’t need to do that?
Any point in the right direction appreciated - I really have no idea.
function (doc) {
if (doc.$doctype == "vehicle")
{
emit(doc.userId, {_id: doc.userId});
}
}
EDIT: Getting closer. I'm not sure exactly what I was expecting, but the result seems a bit 'messy'. Row[0] is the user document, row[n > 0] are the vehicle documents. I guess it's fine when a startkey/endkey is used, but without the results are a bit jumbled up.
function (doc) {
if (doc.$doctype == 'user') {
emit([doc._id, 0], doc);
} else if (doc.$doctype == 'vehicle') {
emit([doc.userId, 1, doc._id], doc);
}
}
A user is described as,
{
"_id": "user:10",
"firstname": “firstnamehere",
"secondname": “secondnamehere",
"userId": "user:10",
"$doctype": "user"
}
a vehicle is described as,
{
"_id": "vehicle:4002”,
“name”: “avehicle”,
"userId": "user:10",
"$doctype": "vehicle",
}
You're getting in the right direction! You already got that right with the global IDs. Having the type of the document as part of the ID in some form is a very good idea, so that you don't get confused later (all documents are in the same "pot").
Here are some minor problems with your current solution (before getting to your actual question):
Don't emit the doc as value in emit(key, value). You can always ask for the document that belongs to a view row by querying with include_docs=true. Having the doc as view value increases the view indexes a lot. When you don't need a specific value, use emit(key, null).
You also don't need the ID in the emit value. You'll get the ID of the document that belongs to a view row as part of the row anyway.
View Collation
Now to your problem of aggregating the vehicles with their user. You got the basic pattern right. This pattern is called view collation, you can read more about it in the CouchDB docs (ignore that it is in the "Couchapp" section).
The trick with view collation is that you return two or more types of documents, but make sure that they are sorted in a way that allows for direct grouping. Thus it is important to understand how CouchDB sorts the view result. See the collation specification for more information on that one. An important key to understanding view collation is that rows with array keys are sorted by key elements. So when two rows have the same key[0], they sort by key[1]. If that's equal as well, key[2] is considered, and so on.
Your map function frist groups users and vehicles by user ID (key[0]). Your map function then uses the fact that 0 sorts before 1 in the second element of the key, so your view will contain the following:
user 1
vehicle of user 1
vehicle of user 1
vehicle of user 1
user 2
user 3
vehicle of user 3
user 4
etc.
As you can see, the vehicles of a user immediately follow their user. Thus you can group this result into aggregates without performing expensive sort or lookup operations.
Note that users are sorted according to their ID, and vehicles within users also according to their ID. This is because you use the IDs in the key array.
Creating Queries
Now that view isn't worth much if you can't query according to your needs. A view as you have it supports the following queries:
Get all users with their vehicles
Get a range of users with their vehicles
Get a single user with its vehicles
Get a single user without vehicles (you could also use the _all_docs view for that though)
Example query for "all users between user 1 and user 3 (inclusive) with their vehicles"
We want to query for a range, so we use startkey and endkey in the query:
startkey=["user:1", 0]
endkey=["user:3", 1, {}]
Note the use of {} as sentinel value, which is required so that the end key is larger than any row that has a key of ["user:3", 1, (anyConceivableVehicleId)]

How to check is the MediaStore.Audio.Media.ARTIST field empty?

I have been working on a MediaPlayer app, where I use the MediaStore.Audio.Media to get all the songs on the SD card and their title, album, artist, etc. tags. I have a custom adapter where I want to check if the Artist field is empty, so I could set "Artist unknown" for that field. The adapter and the cursor I use are in my opinion irrelevant to this question so I'm not going to paste any code here, since this problem occurs outside the adapter as well.
Here is the problem: when an mp3 song doesn't have an artist tag, the cursor for the artist field (the MediaStore.Audio.Media.ARTIST field) returns "". I have no idea what kind of data type that is (it should be String) because whenever I compare it to a String with the value "", the comparison is false. Even if I assign the return value of that field to a temporary String, and than compare that with the before mentioned "", I still get false. I even tried null, "unknown", "", nothing works.
I've really hit a dead end here and any kind of help would be greatly appreciated.
Thank you in advance, Ivan.
I'm using the very same field (MediaStore.Audio.Media.ARTIST), but what I noticed is different.
When you try to retrieve the song's artist info and currently ther's no info available, what you get is <unknown> string.
I wanted to change that info too and I just went for a:
String artist = (((cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)) == null)
|| cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)).equals("")
|| cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)).equals("<unknown>")) ?
"Artist Unknown" : cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)));
the "null and equals.("")" checks should be useless anyway.

Resources