How to create a dict with two sub list? - python

I am trying to loop through two querysets with keys based on dates in the set. Each date has two types of items: Life events and work. The dict should look like this:
Timeline['1980']['event'] = "He was born"
Timeline['1992']['work'] = "Symphony No. 1"
Timeline['1993']['event'] = "He was married"
Timeline['1993']['work'] = "Symphony No. 2"
How do I create this dictionary?
I tried the following:
timeline = defaultdict(list)
for o in opus:
if o.date_comp_f is not None:
timeline[o.date]['work'].append(o)
timeline = dict(timeline)
for e in event:
if e.date_end_y is not None:
timeline[e.date]['event'].append(e)
timeline = dict(timeline)
I keep getting bad Key errors.

t = {}
t['1980'] = {
'event':'He was born',
'work':'None'
}
Or
t = {}
t['1980'] = {}
t['1980']['event'] = 'He was born'
t['1980']['work'] = 'None'

I am not sure what you want, but I guess you want to initialize a dictionary where you can make such assignments. You may need something like this:
from collections import defaultdict
# Create empty dict for assignment
Timeline = defaultdict(defaultdict)
# store values
Timeline['1980']['event'] = "He was born"
Timeline['1992']['work'] = "Symphony No. 1"
# Create a regular dict for checking if both are equal
TimelineRegular = {'1980':{'event':"He was born"},'1992':{'work':"Symphony No. 1"}}
# check
print(Timeline==TimelineRegular)
Output:
>>> True

timeline = {'1980':{'event':'He was born', 'work':'None'}, '1992':{'event':'None', 'work':'Symphony No. 1'}, '1993':{'event':'He was married', 'work':'Symphony No. 2'}}
With results:
>>> timeline['1980']['event']
'He was born'
>>> timeline['1992']['work']
'Symphony No. 1'
>>> timeline['1993']['event']
'He was married'
>>> timeline['1993']['work']
'Symphony No. 2'
This is a nested dictionary, the external dictionary are keys of dates with values of another dictionary. Internal dictionary are keys of work or event with values of the final value.
And to add more:
>>> timeline['2019'] = {'event':'Asked stackoverflow question', 'work':'unknown'}
>>> timeline
{'1980': {'event': 'He was born', 'work': 'None'}, '1992': {'event': 'None', 'work': 'Symphony No. 1'}, '1993': {'event': 'He was married', 'work': 'Symphony No. 2'}, '2019': {'event': 'Asked stackoverflow question', 'work': 'unknown'}}
When you add a new key, you need to make the value your empty dictionary with placeholders for each future key.
timeline['year'] = {'work':'', 'event':''}
or just an empty dictionary, though you may end up with missing keys later
timeline['year'] = {}

Related

How to Split a Dictionary Value into 2 Separate Key Values

I currently have a dictionary where the values are:
disney_data = {
'title': ['Gus (1976)',
'Johnny Kapahala: Back on Board (2007)',
'The Adventures of Huck Finn (1993)',
'The Simpsons (1989)',
'Atlantis: Milo’s Return (2003)']
}
I would like to split up the title from the year value and have a dictionary like:
new_disney_data = {
'title' : ['Gus',
'Johnny Kapahala: Back on Board',
'The Adventures of Huck Finn',
'The Simpsons',
'Atlantis: Milo’s Return'],
'year' : ['1976',
'2007',
'1993',
'1989',
'2003']
}
I tried using the following, but I know something is off - I'm still relatively fresh to python so any help would be greatly apprecated!
for value in disney_data.values():
new_disney_data['title'].append(title[0,-7])
new_disney_data['year'].append(title[-7,-1])
There are two concepts you can use here:
The first would be .split(). This usually works better than indexing in a string (in case someone placed a space after the brackets in the string, for example). Read more.
The second would be comprehension. Read more.
Using these two, here is one possible solution.
titles = [item.split('(')[0].strip() for item in disney_data['title']]
years = [item.split('(')[1].split(')')[0].strip() for item in disney_data['title']]
new_disney_data = {
'title': titles,
'year': years
}
print(new_disney_data)
Edit: I also used .strip(). This removes any trailing whitespace like spaces, tabs, or newlines from the ends of a string. Read more
You're not that far off. In your for-loop you iterate over values of the dict, but you want to iterate over the titles. Also the string slicing syntax is [id1:id2]. So this would probably do what you are looking for:
new_disney_data = {"title":[], "year":[]}
for value in disney_data["title"]:
new_disney_data['title'].append(value[0:-7])
new_disney_data['year'].append(value[-5:-1])
new_disney_data = {
'title': [i[:-6].rstrip() for i in disney_data['title']],
'year': [i[-5:-1] for i in disney_data['title']]
}
this code can do it
import re
disney_data = {
'title': ['Gus (1976)',
'Johnny Kapahala: Back on Board (2007)',
'The Adventures of Huck Finn (1993)',
'The Simpsons (1989)',
'Atlantis: Milo’s Return (2003)']
}
disney_data['year'] = []
for index,line in enumerate(disney_data.get('title')):
match = re.search(r'\d{4}', line)
if match is not None:
disney_data['title'][index] = line.split('(')[0].strip()
disney_data['year'].append(match.group())
print(disney_data)
it searches for every line in the title if there are 4 digits, if exists then add to year, and remove digits and parenthesis from the title.
Something like this
disney_data = {
'title': ['Gus (1976)',
'Johnny Kapahala: Back on Board (2007)',
'The Adventures of Huck Finn (1993)',
'The Simpsons (1989)',
'Atlantis: Milo’s Return (2003)']
}
new_disney_data = {'title': [], 'year': []}
#split title into two columns title and year in new dict
for title in disney_data['title']:
new_disney_data['title'].append(title.split('(')[0]) #split title by '('
new_disney_data['year'].append(title.split('(')[1].split(')')[0]) #split year by ')'
print(disney_data)
print(new_disney_data)
Using split and replace.
def split(data):
o = {'title' : [], 'year' : []}
for (t, y) in [d.replace(')','').split(' (') for d in data['title']]:
o['title'].append(t)
o['year'].append(y)
return o
Using Regular Expession
import re
def regex(data):
r = re.compile("(.*?) \((\d{4})\)")
o = {'title' : [], 'year' : []}
for (t, y) in [r.findall(d)[0] for d in data['title']]:
o['title'].append(t)
o['year'].append(y)
return o

Looping through dictionary and getting TypeError: 'in <string>' requires string as left operand, not list

I'm trying to loop through a list of strings and match/print out any of those strings against a dictionary of words. I seem to get the following error and not too sure why.
Error: TypeError: 'in ' requires string as left operand, not list
Here is the current code i'm working with:
data = ["Great price on the dewalt saw", "cool deal, love it", "nice find", "definitely going to buy"]
words = {'price': ['price', 'compare', '$', 'percent', 'money']}
for d in data:
for word in words.values():
if word in d:
print('Results:')
print(d)
Ideally i'd like to print out all strings that contain any of the price key values.
word is returning a list. You need to loop/iterate over that list (word). You can accomplish it in the following manner -
data = ["Great price on the dewalt saw", "cool deal, love it", "nice find", "definitely going to buy"]
words = {'price': ['price', 'compare', '$', 'percent', 'money']}
for d in data:
for word in words.values():
for s in word :
if s in d:
print('Results:')
print(d)
The above code will find if any string in array of values(that is - any of list from words.values()) in dictionary words is a part of any string in data or not.
Hope it helps !
The issue you have here is that you have a list as a value, so your call to words.values() returns a list that contains another list internally. You could change that to for word in words['price'] if you will only ever have a price key, or you could change it like so:
>>> words = {'price': ['price', 'compare', '$', 'percent', 'money']}
>>> [word for wordlist in words.values() for word in wordlist]
['price', 'compare', '$', 'percent', 'money']
May be its good idea to improve efficiency of accepted answer.
Below is the just an psuedocode to improve time complexity(based on inputs).
visited_dict = {}
results = {}
for d in data:
for k, word in words.items():
can_stop = False
res_val = []
for s in word:
# if same words from another key is searched
# Ex: words = {'price': ['price', 'compare', '$', 'percent', 'money'],
# 'price2':[ 'price', 'something', 'somethingelse']}
# In this case - get the result from visited dictionary to avoid
if s in visited_dict and s not in visited_dict[s]:
# save it to results
# skip further steps
continue
if s in d and s not in res_val:
# store it results
res_val.append(d)
# update visited dict
visited_dict[s] = d
# Save the result to final key to result map
results[k] = res_val # {'price': 'Great price on the dewalt saw'}
# To avoid duplicate
if res_val:
break
Note: its not tested or completely implemented code.
Yes, once implemented properly it may increase space complexity.

switch-case statement for STRINGS in Python

I need to do something similar to the CASE WHEN .. OR .. THEN from SQL in python for STRINGS. For example, if I say "DOG" or "CAT".. my translation is "ANIMAL".
I don't want to use IF ELIF ELIF..
The only solution that i can see is:
l = ['cat','dog', 'turttle']
d = {'animal': ['cat','dog', 'turttle']}
word = 'cat'
if word in l:
for i, j in d.iteritems():
if word in j:
print i
else:
print word
animal
It works but it seems very ugly..
Any other solution?
THANKS!
For your purpose I would suggest that you go with a dict indexed by the name of the animal instead. The list l in your code would then also be redundant because it's simply the keys of this dict.
d = {
'cat': 'animal',
'dog': 'animal',
'turtle': 'animal'
}
word = 'cat'
print(d.get(word, word))
You can do in this way:
animal_list = ['cat','dog', 'turttle']
plant_list = ['tree', 'grass']
d = {'animal': animal_list, 'plant': plant_list}
word = 'tree'
for key, value in d.iteritems():
if word in value:
print key
d = {'animal': ['cat','dog', 'turttle']}
word = 'cat'
if word in d['animal']:
print('animal')
You can use a couple of data structure based efficiencies to scale your program as follows:
Use a dictionary to store the data of what classifies as "animal" or other
Use a set rather than a list to group by classification. This allows for constant time lookup, regardless of how big the set is.
Something like this:
kingdom = {'animal':set(['Cat','Dog','Turtle']), 'plant':set(['Rosemary','Thyme'])}
word = 'cat'
for family in kingdom:
if word in kingdom[family]: # here is where constant time lookup occurs
print family
else:
print word
Alternately, you could define classes for "Animal" and "Plant", etc... depending on how much functionality is specific to the "Animal" or "Plant" stuff. I do subscribe to the principle of avoiding placeholder code, so would recommend not to look into classes unless you have reason to implement it.
what happened if I have 1M of words and translations?
An alternate approach is to store your data in a way that's convenient for defining it but before the main body of your code, invert the data (once) into a form that's more efficient for runtime:
by_kingdoms = {
'animal': {'cat', 'dog', 'turtle'},
'plant': {'rosemary', 'thyme'},
}
by_families = {}
for kingdom, families in by_kingdoms.items():
for family in families:
by_families[family] = kingdom
word = 'cat'
print(by_families[word])
This assumes well-structured data but you can even have overlap by making the values of the by_families dictionary lists of kingdoms in which this family might appear:
from collections import defaultdict
by_kingdoms = {
'animal': {'cat', 'dog', 'turtle', 'bird of paradise'},
'plant': {'rosemary', 'thyme', 'bird of paradise'},
}
by_families = defaultdict(list)
for kingdom, families in by_kingdoms.items():
for family in families:
by_families[family].append(kingdom)
word = 'bird of paradise'
print(by_families[word])

how to use "in" condition with many text define in python

i want to get correct result from my condition, here is my condition
this is my database
and here is my code :
my define text
#define
country = ('america','indonesia', 'england', 'france')
city = ('new york', 'jakarta', 'london', 'paris')
c1="Country"
c2="City"
c3="<blank>"
and condition ("text" here is passing from select database, ofc using looping - for)
if str(text) in str(country) :
stat=c1
elif str(text) in str(city) :
stat=c2
else :
stat=c3
and i got wrong result for the condition, like this
any solution to make this code work ? it work when just contain 1 text when using "in", but this case define so many text condition.
If i understood you correctly you need.
text = "i was born in paris"
country = ('america','indonesia', 'england', 'france')
city = ('new york', 'jakarta', 'london', 'paris')
def check(text):
for i in country:
if i in text.lower():
return "Country"
for i in city:
if i in text.lower():
return "City"
return "<blank>"
print(check(text))
print(check("I dnt like vacation in america"))
Output:
City
Country
You could be better off using dictionaries. I assume that text is a list:
dict1 = {
"countries" : ['america','indonesia', 'england', 'france'],
"city" : ['new york', 'jakarta', 'london', 'paris']
}
for x in text:
for y in dict1['countries']:
if y in x:
print 'country: ' + x
for z in dict1['city']:
if z in x:
print 'city: ' + x
First of all, check what you are testing.
>>> country = ('america','indonesia', 'england', 'france')
>>> city = ('new york', 'jakarta', 'london', 'paris')
>>>
>>> c1="Country"
>>> c2="City"
>>> c3="<blank>"
Same as your setup. So, you are testing for the presence of a substring.
>>> str(country)
"('america', 'indonesia', 'england', 'france')"
Let's see if we can find a country.
>>> 'america' in str(country)
True
Yes! Unfortunately a simple string test such as the one above, besides involving an unnecessary conversion of the list to a string, also finds things that aren't countries.
>>> "ca', 'in" in str(country)
True
The in test for strings is true if the string to the right contains the substring on the left. The in test for lists is different, however, and is true when the tested list contains the value on the left as an element.
>>> 'america' in country
True
Nice! Have got got rid of the "weird other matches" bug?
>>> "ca', 'in" in country
False
It would appear so. However, using the list inclusion test you need to check every word in the input string rather than the whole string.
>>> "I don't like to vacation in america" in country
False
The above is similar to what you are doing now, but testing list elements rather than the list as a string. This expression generates a list of words in the input.
>>> [word for word in "I don't like to vacation in america".split()]
['I', "don't", 'like', 'to', 'vacation', 'in', 'america']
Note that you may have to be more careful than I have been in splitting the input. In the example above, "america, steve" when split would give ['america,', 'steve'] and neither word would match.
The any function iterates over a sequence of expressions, returning True at the first true member of the sequence (and False if no such element is found). (Here I use a generator expression instead of a list, but the same iterable sequence is generated).
>>> any(word in country for word in "I don't like to vacation in america".split())
True
For extra marks (and this is left as an exercise for the reader) you could write
a function that takes two arguments, a sentence and a list of possible matches,
and returns True if any of the words in the sentence are present in the list. Then you could use two different calls to that function to handle the countries and the
cities.
You could speed things up somewhat by using sets rather than lists, but the principles are the same.

Python LOB to List

Using:
cur.execute(SQL)
response= cur.fetchall() //response is a LOB object
names = response[0][0].read()
i have following SQL response as String names:
'Mike':'Mike'
'John':'John'
'Mike/B':'Mike/B'
As you can see it comes formatted. It is actualy formatted like:\\'Mike\\':\\'Mike\\'\n\\'John\\'... and so on
in order to check if for example Mike is inside list at least one time (i don't care how many times but at least one time)
I would like to have something like that:
l = ['Mike', 'Mike', 'John', 'John', 'Mike/B', 'Mike/B'],
so i could simply iterate over the list and ask
for name in l:
'Mike' == name:
do something
Any Ideas how i could do that?
Many thanks
Edit:
When i do:
list = names.split()
I receive the list which is nearly how i want it, but the elements inside look still like this!!!:
list = ['\\'Mike\\':\\'Mike\\", ...]
names = ['\\'Mike\\':\\'Mike\\", ...]
for name in names:
if "Mike" in name:
print "Mike is here"
The \\' business is caused by mysql escaping the '
if you have a list of names try this:
my_names = ["Tom", "Dick", "Harry"]
names = ['\\'Mike\\':\\'Mike\\", ...]
for name in names:
for my_name in my_names:
if myname in name:
print myname, " is here"
import re
pattern = re.compile(r"[\n\\:']+")
list_of_names = pattern.split(names)
# ['', 'Mike', 'Mike', 'John', 'John', 'Mike/B', '']
# Quick-tip: Try not to name a list with "list" as "list" is a built-in
You can keep your results this way or do a final cleanup to remove empty strings
clean_list = list(filter(lambda x: x!='', list_of_names))

Categories

Resources