Python : Iterate over dictionaries to read arguments - python

I have a dictionary weeks that is populated using a for loop. The dictionary contains arguments passed to a function. I'd like to update the code to read second argument and pass that to the function.
from datetime import date, datetime, timedelta
weeks = {}
def generate(date):
# generate 8 rows with 4 cells each
for d in range(1, 32, 4):
start = (date + timedelta(days=d)).strftime('%Y-%m-%d')
week = pd.date_range(start, periods=4).to_pydatetime().tolist()
weeks[d] = week
print(weeks)
def create(arg1):
# do something
return ...
This function populates a dictionary with dates as a list of values.
{1: [datetime.datetime(2021, 10, 13, 0, 0), datetime.datetime(2021, 10, 14, 0, 0), datetime.datetime(2021, 10, 15, 0, 0), datetime.datetime(2021, 10, 16, 0, 0)], 5: [datetime.datetime(2021, 10, 17, 0, 0), datetime.datetime(2021, 10, 18, 0, 0), datetime.datetime(2021, 10, 19, 0, 0), datetime.datetime(2021, 10, 20, 0, 0)],.......
Now I'd like to either modify the weeks dictionary or create a new dictionary that I'll iterate over to read the second argument of the function.
The function call:
[create(i)] for i in weeks[1]
I'd like to modify this call to include a second argument which is read from the dictionary with same structure as well. Pseudocode below:
[create(i,j)] for i,j in weeks[1], value[1]
where value is the new dictionary with populate, if we don't modify the existing dict weeks. I'd appreciate advise on which approach makes sense and how can I modify the function call to pass two arguments.
value dict will look like this:
value = {1: [1000, 1200, 1400, 1600], 5: [2000, 2200, 2400, 2600]}

Use zip to iterate over two lists in parallel, it will yield pairs in tuples
[create(i, j) for i, j in zip(weeks[1], value[1]))

Related

Compare dictionary keys (datetime) with list of tuples[1] and if matches return tuple[0]

I am a beginner(ish) with Python and having trouble with getting the correct syntax for this. Any help is greatly appreciated!
I have a dictionary and a list of tuples. I would like to compare the key of my dictionary to a value in the tuple, and if meets criteria return a different tuple value. Here's the illustration:
dictionary = {datetime.datetime(2022, 4, 12, 9, 30): 30, datetime.datetime(2022, 4, 12, 11, 0): 60, datetime.datetime(2022, 4, 12, 13, 0): 30}
tuplelist = [(1, datetime.time(6, 45, 21)), (2, datetime.time(7, 15, 21)), (3, datetime.time(7, 45, 21)...etc)
The goal is to see which increment of 30 minutes my dictionary key falls into, and update it with the increment number stored in tuple list. What I tried:
for k,y in dictionary:
for i, t in tuplelist:
if t <= k <= (t+ datetime.timedelta(minutes = 30)):
dictionary[k] = t
The error I got is unable to unpack non iterable type datetime.
Any help and/or explanation is welcome! I am really enjoying learning to code but not from a CS background so always looking for the how it works in addition to just the correct syntax.
Thank you!
Update for working solution:
newdic = {}
for k,v in dictionary.items():
for item in mylist:
i, t = item
if t <= k.time() <= (datetime.combine(datetime.today(),t) + datetime.timedelta(minutes=30)).time():
newdic.update({i : v})
else:
continue
This is not the complete answer. See if it helps resolve early issues up to the comment.
import datetime
dictionary = {datetime.datetime(2022, 4, 12, 9, 30): 30,
datetime.datetime(2022, 4, 12, 11, 0): 60,
datetime.datetime(2022, 4, 12, 13, 0): 30}
tuplelist = [(1, datetime.time(6, 45, 21)), (2, datetime.time(7, 15, 21)),
(3, datetime.time(7, 45, 21),)]
for k, y in dictionary.items():
for item in tuplelist: # get each tuple from the list
i, t = item # unpack the tuple into i and t
print(f'{i=} {t=}') # Check i and t values
# if t <= k <= (t + datetime.timedelta(minutes=30)):
# dictionary[k] = t

How to print query results in Python including column names

When printing PostgreSQL query results I only see the result values, I would like to see the column name along with the result values
postgreSQL_select_Query = "SELECT epic,timestamp FROM market_data_historic s1 WHERE timestamp = (SELECT MAX(timestamp) FROM market_data_historic s2 WHERE s1.epic = s2.epic)"
cursor.execute(postgreSQL_select_Query)
# Close the connection
result=(cursor.fetchall())
for row in result:
print (row)
This is the result I get:
('CC.D.LCO.USS.IP', datetime.datetime(2019, 11, 13, 22, 0))
('IX.D.DAX.DAILY.IP', datetime.datetime(2019, 7, 23, 4, 0))
('KB.D.ELECTY.DAILY.IP', datetime.datetime(2020, 1, 24, 16, 0))
('CS.D.ALUMINIUM.TODAY.IP', datetime.datetime(2019, 7, 23, 1, 0))
('CS.D.NZDCAD.TODAY.IP', datetime.datetime(2020, 1, 24, 21, 0))
('CS.D.CADCNH.TODAY.IP', datetime.datetime(2020, 1, 16, 8, 0))
How can I get it to be like this:
(epic:'CC.D.LCO.USS.IP',timestamp: datetime.datetime(2019, 11, 13, 22, 0))
(epic:'IX.D.DAX.DAILY.IP',timestamp: datetime.datetime(2019, 7, 23, 4, 0))
(epic:'KB.D.ELECTY.DAILY.IP',timestamp: datetime.datetime(2020, 1, 24, 16, 0))
(epic:'CS.D.ALUMINIUM.TODAY.IP',timestamp: datetime.datetime(2019, 7, 23, 1, 0))
(epic:'CS.D.NZDCAD.TODAY.IP',timestamp: datetime.datetime(2020, 1, 24, 21, 0))
(epic:'CS.D.CADCNH.TODAY.IP',timestamp: datetime.datetime(2020, 1, 16, 8, 0))
Use the cursor.description attribute to retrieve column names and convert results to dictionaries:
result = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
for row in result:
print (dict(zip(columns, row)))
Alternatively, you can use Real dictionary cursor or Named tuple cursor.
See also DictCursor vs RealDictCursor.
Try the description attribute of cursor:
Read-only attribute describing the result of a query. It is a sequence of Column instances, each one describing one result column in order. The attribute is None for operations that do not return rows or if the cursor has not had an operation invoked via the execute*() methods yet.
For compatibility with the DB-API, every object can be unpacked as a 7-items sequence: the attributes retuned this way are the following. For further details and other attributes available check the Column documentation.
name: the name of the column returned.
type_code: the PostgreSQL OID of the column.
display_size: the actual length of the column in bytes.
internal_size: the size in bytes of the column associated to this column on the server.
precision: total number of significant digits in columns of type NUMERIC. None for other types.
scale: count of decimal digits in the fractional part in columns of type NUMERIC. None for other types.
null_ok: always None as not easy to retrieve from the libpq.

Adding up datetime.datetime that are in single list

I've looked everywhere and I can't seem to find what I need. I have a list that contains datetime that I need to combine to find the sum. This list is parsed from a file and can have any number of datetime items in it. It looks like such for an example.
[datetime.datetime(1900, 1, 1, 1, 19, 42, 89000), datetime.datetime(1900, 1, 1, 2, 8, 4, 396000), datetime.datetime(1900, 1, 1, 0, 43, 54, 883000), datetime.datetime(1900, 1, 1, 0, 9, 13, 343000)]
The code I'm using to get this is this
time = [i[8] for i in smaller_list]
try:
times = [datetime.datetime.strptime(x, "%H:%M:%S.%f") for x in time]
except ValueError:
times = [datetime.datetime.strptime(x, "%M:%S.%f") for x in time]
Time gets the varibles from a larger nested list that I created to separate lines of data. I've tried datetime.datetime.combine() but I'm not really sure how to use this for items in a single list. Do I need to create a nested list of datetimes and sum them up? How do I iterate though this list and combine all the times for a sum? If I do have to create a nested list, how do I iterate through it to add up the times? Trying to wrap my head around this.
When you print time this is what is returned so the example list directly helps me.
[datetime.datetime(1900, 1, 1, 1, 19, 42, 89000), datetime.datetime(1900, 1, 1, 2, 8, 4, 396000), datetime.datetime(1900, 1, 1, 0, 43, 54, 883000), datetime.datetime(1900, 1, 1, 0, 9, 13, 343000)]
This is what the original times look like. I need to add up times such as these for total time. Usually in minutes with micro seconds included and rarely hours.
25:21.442
09:52.149
28:03.604
27:12.113
If anyone else runs into this problem here is the code I used.
time = [i[8] for i in smaller_list]
sumtime = datetime.timedelta()
for i in time:
try:
(h, m, s) = i.split(':')
d = datetime.timedelta(hours=int(h), minutes=int(m), seconds=float(s))
except ValueError:
(m, s) = i.split(':')
d = datetime.timedelta(minutes=int(m), seconds=float(s))
sumtime += d
print(str(sumtime))
If you're learning python it's pretty confusing trying to wrap your mind around date time and time delta. For duration's you need to use timedelta. You have to split the values up and pass the correct values to time delta and then you can sum them up to find the duration. Hopefully this helps someone out there.
If you need to round the microseconds to seconds you can use this code in place of d.
d = datetime.timedelta(minutes=int(m), seconds=round(float(s)))

max date in python list

I have an list:
a=[datetime.date(2010,10,20),1,4,datetime.date(2013,10,20)]
As you can see the list contains different types of elements. How can I get the max date within the list?
My attempt:
from datetime import datetime
b=datetime.max(a)
print b
For guidence Find oldest/youngest datetime object in a list
from datetime import datetime
datetime_list = [
datetime(2009, 10, 12, 10, 10),
datetime(2010, 10, 12, 10, 10),
datetime(2010, 10, 12, 10, 10),
datetime(2015, 2, 12, 10, 10), # future
datetime(2016, 2, 12, 10, 10), # future
]
oldest = min(datetime_list)
youngest = max(datetime_list)
The prior post has filter to exclude future events
First, keeping dates and integers together in the same list -- except as an intermediate step -- can be a sign your data structure isn't appropriate. That said, you can easily take the max only of the dates by using a generator expression:
>>> import datetime
>>> a=[datetime.date(2010,10,20),1,4,datetime.date(2013,10,20)]
>>> max(d for d in a if isinstance(d, datetime.date))
datetime.date(2013, 10, 20)

Multiple loop control variables in Python for loop

I came across a situation where I need to implement a for loop with more than one loop control variable. Basically this is what I am trying to do
Java:
for (int i=0,j=n; i<n,j>=0; i++, j--)
do my stuff
How do I do this in Python?
for i in range(0,n), j in range(n-1,-1,-1):
do my stuff
But this doesn't work. What would be the right syntax here? Also, is there a more elegant(pythonic) construct for the use-case?
For your specific example, it doesn't look like you really need separate variables in the loop definition itself. You can just iterate over the i values and construct the j values by doing n-i:
for i in range(0, n):
j = n-i
# do stuff
In general, you can't specify multiple values in the for statement if they depend on each other. Instead, use the for to iterate over some "base" value or values from which the others can be derived.
You can specify multiple values in the for loop, but they must be drawn from a single iterable:
for i, j in zip(range(0, n), range(n, 0, -1)):
# do stuff
This takes i from the first range (0 to n-1) and j from the second (n to 1). zip creates a new iterable by componentwise pairing the elements of the iterables you give it.
The thing to remember is that Python for loops are not like loops in Java/C, which have an initialize/check end condition/update structure that repeatedly modifies some persistent loop index variable. Python for loops iterate over a "stream" of values provided by a "source" iterable, grabbing one value at a time from the source. (This is similar to foreach-type constructs in some other languages.) Whatever you want to iterate over, you need to get it into an iterable before you begin the loop. In other words, every Python for loop can be thought of as roughly analogous to something like:
for (i=iterable.getNextValue(); iterable.isNotEmpty(); i=iterable.getNextValue())
You can't have the loop initialization be different from the loop update, and you can't have those be any operation other than "get the next value", and you can't have the end condition be anything other than "is the iterable exhausted". If you want to do anything like that, you have to either do it yourself inside the loop (e.g., by assigning a secondary "loop variable" as in my example, or by checking for a custom loop exit condition and breaking out), or build it into the "source" that you're iterating over.
A lot depends on iterators you want. Here's a couple of options. What they have in common is that for... in... will traverse over lists, tuples, and anything else which supports iteration. So you could loop over a list of known values or a generator which produces an arbitrary series of values. The for... in... is the same regardless.
Here's some standard python tricks:
nested loops
for i in range(10):
for j in range (10):
print i, j
This is simple and clear, but for complex iterations it may get very deeply nested. Here range is a generator, which means it produces an iteration over a series (in this case, 10 numbers - but it could be any arbitrary stream of values))
zip
for multiple iterators you can use zip() which creates an iterable object that produces a value from each of several of iterables at the same time. You can use multple assignment inside the for loop to grab pieces out of the zip
a = [1,2,3,4]
b = ['a','b','c','d']
for number, letter in zip (a, b):
print letter, ":", number
# a : 1
# b : 2
# c : 3
# d : 4
zip will stop when the first member is exhausted:
a = [1,2]
b = ['a','b','c','d']
for number, letter in zip (a, b):
print letter, ":", number
# a : 1
# b : 2
zip also uses generators:
test = zip (range(10), range(10,20))
for item in test: print item
#(0, 10)
#(1, 11)
#(2, 12)
#(3, 13)
#(4, 14)
#(5, 15)
#(6, 16)
#(7, 17)
#(8, 18)
#(9, 19)
itertools
For more complex iterations there's a lot of great tools in the itertools module This is particularly nice for things like getting all of the products or permutations of multiple iterators. It's worth checking out but I think it's more than you need
You can create a list comprehension using more than one loop control variable:
>>> n = 10
>>> stuff = [i*j for i in range(n) for j in range(n-1,-1,-1)]
>>> stuff
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 27, 24, 21, 18, 15, 12, 9, 6, 3, 0, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0, 54, 48, 42, 36, 30, 24, 18, 12, 6, 0, 63, 56, 49, 42, 35, 28, 21, 14, 7, 0, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0, 81, 72, 63, 54, 45, 36, 27, 18, 9, 0]

Categories

Resources