am trying to build a logic which am not quit sure how to do with python. I have the following dictionary
{datetime.datetime(2011, 7, 18, 13, 59, 25): (u'hello-world', u'hello world'), datetime.datetime(2011, 7, 17, 15, 45, 54): (u'mazban-archeticture', u'mazban arch'), datetime.datetime(2011, 7, 7, 15, 51, 49): (u'blog-post-1', u'blog post 1'), datetime.datetime(2011, 7, 8, 15, 54, 5): (u'blog-post-2', u'blog post 2'), datetime.datetime(2011, 7, 18, 15, 55, 32): (u'blog-post-3', u'blog post 3')}
I want to iterate through the dictionary, find out if the date is equal today's date and then use the inner dictionary to build a url using the first value as a slug. Am able to iterate but I don't know how to fetch the inner value
# will only print dates
for i in dic:
print i
In python when you use 'for x in dic' it is the same as to use 'for x in dic.keys()' - you are iterating trough only keys not (key,value) pairs.
To do what you want you can take a look at the items() and iteritems() dictionary methods, they allows you to get access to (key,value) pairs:
for key,value in dic.iteritems():
if key == datetime.today(): # or (datetime.today() - key).seconds == <any value you expect>
# since value is a tuple(not a dict) and you want to get the first item you can use index 0
slug = value[0]
Read more about dictionaries and supported methods
If you want to access the value then you subscript the dictionary, unless you actually want tuples this is usually less hassle than using either .items() or .iteritems() methods:
for i in dic:
print i, dic[i]
BTW, you say 'inner dictionary' but you only have one dictionary, the values are tuples.
Related
I have a script which imports data and I am storing these in nested lists.
I have one list which instructs how many elements from each sub-list are to be discarded.
How do I do this?
I know how to do it manually, but I want to be able to upload a csv file into my program, and then let it run.
I have run the same line of data twice in csv file to try and make it simpler for me to fix, so I have
starting_index = [203,203]
but in principle this could have a 100 or so elements of different number.
I then have a whole series of nested lists. The number of elements in my starting_index matches the number of sub-lists within each list so at the moment there are only two sub-lists in each nested list.
I wanted to define a function that I could call on to pare each list. I know what is wrong with my code, but I do not know how to make it work.
def index_filter(original_list, new_list):
for i in starting_index:
print(i)
for index, value in enumerate(original_list):
for item,element in enumerate(value):
if item >= i:
new_list[index].append(element)
I realise now that this does not work, and the problems is the
for i in starting_index:
because when it finishes the first element in starting index, it then goes on to the next and appends more data. It doesn't error, but it does not do what I wanted it to do. I just want to remove in this case the first 203 elements from sub-list 1, and the first 203 elements from sub list two, but in principle those numbers will change.
I try and use enumerate all the time, and perhaps it's not appropriate here.
How can I solve this?
Thanks
Edit: Some sample data:
starting_index = [2,1,3]
list_one = [[15,34,67,89,44], [44,23,67,88,45,67,233,567,41,56.4],[45,6734,5,67,29,55,6345,23,89,45,6,8,3,4,5,876]]
ideal result:
list_one = [[67,89,44],[23,67,23,67,88,45,67,233,567,41,56.4],[67,29,55,6345,23,89,45,6,8,3,4,5,876]]
I have just come across the del statement which I am looking at, and I'll also have a look at the slice suggestion. Thanks
Edit: I tried the solution but I can't get it to work.
I tried that but when I put some test data in I get back the original unaltered list.
How do I access the output?
My test script:
original_list=[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], [16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38]]
starting_index=[3,6]
def index_filter(original_list, starting_index):
return [value[i:] for i, value in zip(starting_index, original_list)]
index_filter(original_list, starting_index)
print(index_filter)
print(original_list)
Outputs a strange message and the original unaltered list
<function index_filter at 0x039CC468>
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38]]
Thank you
You need to loop through the starting_index and original_list in parallel, so use zip().
And you can use the slice value[i:] to get the part of a list starting at an index, rather than looping.
def index_filter(original_list, starting_index):
return [value[i:] for i, value in zip(starting_index, original_list)]
original_list=[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], [16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38]]
starting_index=[3,6]
new_list = index_filter(original_list, starting_index)
print(new_list)
I'm running into a problem with using DateTime as a dict key. My goal is to bring in information from one data source that includes Datetime, and then look up in a dictionary and return all values for keys that are within 2 days +- of the input DateTime.
For example, my input would be:
datetime.datetime(2018, 9, 20, 12, 48)
My dictionary to reference would be:
example = {datetime.datetime(2018, 9, 20, 14, 43):'A', datetime.datetime(2018, 9, 18, 19, 41):'B', datetime.datetime(2018, 9, 15, 9, 12):'C'}
In that case, I would return: A, B
I have considered sorting the dictionary and then creating a dictionary of indexes maybe for odd-numbered dates, then taking in my input date, figuring the base date +- 2 of the input date, referencing the index dict, and then using those indexes to loop through the reference dict only between the indexes and return all values that are there.
My main issue is that I can't predict what the dict datetimes will be or the input datetimes so I'm just not certain if I can return values for a range of keys in a dict other than by looping through the index of the keys in a sorted order. Doing a for loop for all keys is not efficient here because of the number of keys to look through -- I am already reducing this list by deduplicating down as much as possible and only bringing in the minimum amount of reference data.
One other item is that my inputs will be 100,000s of datetimes to look up, many of which will be minutes, seconds, or hours off from each other, so reducing the number of lookups and for looping will be essential to keep the runtime down.
I apologize if this isn't quite a proper question with full code to look at but I basically am not sure where to start on this issue, so I didn't think it would help anyone to put anything else in except for example input and dictionary with output goal.
First, sort the dictionary dates and transform a dictionary into list of sorted tuples :
dic_dates = {
datetime.datetime(2018, 9, 20, 14, 43):'A',
datetime.datetime(2018, 9, 18, 12, 41):'B',
datetime.datetime(2018, 9, 15, 9, 12):'C'
}
sorted_dates = sorted(dic_dates.items())
Then use bisect to find the position of your date inside that list :
dat = datetime.datetime(2018, 9, 20, 12, 48)
insert_index = bisect.bisect_left(sorted_dates, (dat,None))
Look from this position to the left and break as soon as an element do not verify the condition, then do the same starting from the position to the right. (You can use your own conditions as I found that was quite unclear in you example - +-2days should not select 'B' IMO but that's not the point)
if insert_index:
#if insert_index = 0, do not loop on left side
dat_min = dat - datetime.timedelta(days=2)
for d in sorted_dates[insert_index-1::-1]:
if d[0] > dat_min:
print(d[1])
else:
break
dat_max = dat + datetime.timedelta(days=2)
for d in sorted_dates[insert_index:]:
if d[0] < dat_max:
print(d[1])
else:
break
EDIT
One example of bisct_left implementation :
def bisect_left(l, e, start = 0):
if not l:
return start
pos = int(len(l)/2)
if l[pos] < e and (pos+1 >= len(l) or l[pos+1] > e):
return start + pos + 1
elif l[pos] >= e:
return bisect_left(l[:pos], e, start)
else:
return bisect_left(l[pos:], e, start+pos)
I strongly advice you to use bisect as it will be quicker and more reliable.
I have a dictionary with a datetime as key and a number as value.
dict = {datetime.datetime(2015, 7, 8, 1 ,15, 3):3, datetime.datetime(2015, 7, 8, 8 ,15, 8):4,
datetime.datetime(2015, 7, 9, 7 ,15, 0):4 , datetime.datetime(2015, 7, 9, 10 ,30, 0):8}
I want this result:
result = {datetime.datetime(2015, 7, 9, 07 ,15, 0):4 , datetime.datetime(2015, 7, 9, 10 ,30, 0):8}
or
result = [4, 8]
I edited my dict. Before it was string keys and values:
dict = {'08/07/2015 01:15':'3', '08/07/2015 08:15':'5',
'09/07/2015 07:15':'4', '09/07/2015 10:30':'8'}
You can simply iterate over your keys and find matches:
def extract(data, day):
return {key: data[key] for key in data if day in key}
dict = {'08/07/2015 01:15':'3', '08/07/2015 08:15':'5',
'09/07/2015 07:15':'4', '09/07/2015 10:30':'8'}
print extract(dict, '09/07/2015')
{'09/07/2015 07:15': '4', '09/07/2015 10:30': '8'}
second output can be achieved analogously
def extract(data, day):
return [data[key] for key in data if day in key]
Since your keys are strings, just loop and match the string:
{key: value for key, value in dict.items() if key.startswith('09/07/2015')}
or to get just the values:
[value for key, value in dict.items() if key.startswith('09/07/2015')]
If you really have datetime.datetime() objects, you can match the output of the datetime.date() method against a datetime.date object:
from datetime import date
[value for key, value in dict.items() if key.date() == date(2015, 7, 9)]
You can do this in several ways but the key is to work with the date. Transform that string into a datetime object first using strptime (https://docs.python.org/2/library/datetime.html#datetime.datetime.strptime) then, you can get your unique days by transforming back with strftime with the appropriate format.
Finally, you can search in your keys with "in" using the parsed days.
I have a dictionary which consist of lists. Now how will it be possible to add a variable/element in the list for the example provided below.
inventory = {
'gold': 20,
'bag': ['chocolate', 'chips', 'food']
}
Now how do I add something in the list bag.
I have already tried this but it does not work.
inventory.bag.append('test')
inventory.bag.insert('test')
You need to use subscription, so object[...], to address elements in the dictionary:
inventory['bag'].append('test')
Here inventory['bag'] retrieves the value associated with the 'bag' key. This is a list object, so you can then call the append() method on that result.
You need access dict value like inventory['bag'], then because the value is a list, you just need call append method
inventory['bag'].append('test')
Demo of How to Append and Insert element in the list.
List append() method will add given element at the last.
>>> l1 = [11, 12, 13]
>>> l1.append(20)
>>> l1
[11, 12, 13, 20]
# ^
List insert() method will take two arguments, First is index where you want to insert given element and second is element which need to insert.
>>> l1.insert(1, 22)
>>> l1
[11, 22, 12, 13, 20]
# ^
Consider dictionary where key i.e.number have value as List Object.
>>> d = {"number":[11, 12]}
>>> d["number"]
[11, 12]
>>> d["number"].append(22)
>>> d
{'number': [11, 12, 22]}
>>> d["number"].insert(2, 20)
>>> d["number"]
[11, 12, 20, 22]
>>>
Every example of list or set usage in Python seems to include trivial cases of integers but I have two lists of objects where the name attribute defines whether two objects instances are "the same" or not (other attributes might have different values).
I can create a list that contains all items from both lists, sorted, with
tmpList = sorted(list1 + list2, key=attrgetter('name'))
but how do I do the same so that list items that have the same value in the name attribute are selected from the second list?
E.g combining these two lists
list1 = [obj('Harry',18), obj('Mary',27), obj('Tim', 7)]
list2 = [obj('Harry', 22), obj('Mary', 27), obj('Frank', 40)]
would result in
list = [obj('Harry',22), obj('Mary', 27), obj('Tim', 7), obj('Frank', 40)]
(I used obj() as a short-hand notation for an object that has two attributes.)
It seems like I can't use the attrgetter() function in most set and list functions like I can with the sorted() function so I can't figure out how I'm supposed to do this. I suspect I could use a lambda function, but I'm not too familiar with functional programming so I don't seem to manage to figure it out.
The naive solution (first pick all items that are unique in both lists and then combine that list with what is left of the second list) seems quite long-winded so there must be a simpler way in Python.
Sounds to me like you might be better off with a dict instead of a list, using the name as the key, and the rest of the object as value. Then you can simply dict1.update(dict2).
>>> dict1 = {"Harry": 18, "Mary": 27, "Tim": 7}
>>> dict2 = {"Harry": 22, "Mary": 27, "Frank": 40}
>>> dict1.update(dict2)
>>> dict1
{'Tim': 7, 'Harry': 22, 'Frank': 40, 'Mary': 27}
Yes. The easy way is a dictionary.
list1 = {"Harry": 18, "Mary": 27, "Tim": 7}
list2 = {"Harry": 22, "Mary": 27, "Frank": 40}
list1.update(list2)
list is now {'Harry':22, 'Mary': 27, 'Tim': 7, 'Frank': 40}
If your data is more than just a number, that's OK. You can put any kind of object as the value for a dictionary.
list1['Harry'] = (1,"weee",54.55)
You can implement de __eq__ attribute in your object. Based on that you can compare your objects with the == operator.