I am trying to calculate items within list, adding together string and integer.
Function does not work:
x_list = ['string', '100', 'string']
def calculate_str_and_int():
str_x = x_list[1]
sum_x = int(str_x) + 200
print(sum_x)
Expected output:
['string', 300, 'string']
Thank you in advance!
You should re-assign the value in position 1 to the newly calculated value, like e.g:
x_list = ['string', '100', 'string']
def calculate_str_and_int():
str_x = x_list[1]
sum_x = int(str_x) + 200
x_list[1] = sum_x
print(x_list)
calculate_str_and_int()
This will print:
['string', 300, 'string']
Related
I am relatively new to python programming. I was trying some challenges in online to thorough my programming skills. I got stuck with the below code. Please someone help here.
ress = {'product': ['Mountain Dew Spark', 'pepsi'], 'quantity': ['7', '5']}
prods_list = []
prods_dict = {}
for k , v in ress.items():
if "product" in k:
if len(ress['product']) > 1:
entity_names = {}
entity_list = []
for i in range(len(ress['product'])):
prod = "product_" + str(i)
entity_names['product'] = ress['product'][i]
entity_names['quantity'] = ress['quantity'][i]
entity_list.append(entity_names)
prods_dict[prod] = entity_list
prods_list.append(prods_dict)
print(prods_list)
i am expecting output as below
Expected output:
[{"product_0":
{"quantity" : "7",
"product" : "mountain dew spark"}
},
{"product_1" : {
"quantity" : "5",
"product" : "pepsi"
}}]
Actual output:
[{'product_0': [{'product': 'pepsi', 'quantity': '5'},
{'product': 'pepsi', 'quantity': '5'}],
'product_1': [{'product': 'pepsi', 'quantity': '5'},
{'product': 'pepsi', 'quantity': '5'}]}]
Please note i want my code work for single values as well like ress = {'product': ['Mountain Dew Spark'], 'quantity': ['7']}
This is one way you can achieve it with regular loops:
ress = {'product': ['Mountain Dew Spark', 'pepsi'], 'quantity': ['7', '5']}
prods_list = []
for key, value in ress.items():
for ind, el in enumerate(value):
prod_num = 'product_' + str(ind)
# If this element is already present
if (len(prods_list) >= ind + 1):
# Add to existing dict
prods_list[ind][prod_num][key] = el
else:
# Otherwise - create a new dict
prods_list.append({ prod_num : { key : el } })
print(prods_list)
The first loop goes through the input dictionary, the second one through each of its lists. The code then determines if a dictionary for that product is already in the output list by checking the output list length. If it is, the code simply appends new inner dict for that product. If it is not - the code creates an outer dict for that product - and an inner one for this particular value set.
Maybe using a list comprehension along with enumerate and zip might be easier:
>>> res = {'product': ['Mountain Dew Spark', 'pepsi'], 'quantity': ['7', '5']}
>>> prods_list = [
... {f'product_{i}': {'quantity': int(q), 'product': p.lower()}}
... for i, (q, p) in enumerate(zip(res['quantity'], res['product']))
... ]
>>> prods_list
[{'product_0': {'quantity': 7, 'product': 'mountain dew spark'}}, {'product_1': {'quantity': 5, 'product': 'pepsi'}}]
This assumes that there will be no duplicate product entries. In that case, you would need to use a traditional for loop.
I have a user input which comes in as follows:
j = ['1', '2', '3', '4', '5-6', '7-9']
I want to go through this list, identify any 'ranges' such as 7-8, or 5-99 etc.
With these remove the - and put the first and second values into range()
So far I have the following, I just can't figure out how to get the values into the right place, perhaps I need to select the number before the - and after the - ?
for item in j:
if "-" in item:
item = item.split("-")
# list(map(str, range(244, 247)))
for r in item:
print(r)
print('next')
# something like this?
list(map(str, range(int(item[0]), int(item[1]))))
EDIT
Taking into account jonrsharpe's comment:
for item in j:
if "-" in item:
start, stop = item.split("-")
print('start:' + start + ' end: ' + stop)
list(map(str, range(int(start), int(stop))))
This returns a type error TypeError: 'str' object is not callable
Assuming the output expected is j = [1, 2, 3, 4, 5, 6, 7, 8, 9]
You can create a blank list, process each element depending on whether or not it has a "-"
l = ['1', '2', '3', '4', '5-6', '7-9']
ll = []
for element in l:
if '-' in element:
sublist = element.strip().split('-')
sublist = list(range(int(sublist[0]), int(sublist[1]) + 1))
ll += sublist
else:
ll.append(int(element))
One approach is to create a list of items for both single numbers and ranges, and then use this as the argument to range:
j = ['1', '2', '3', '4', '5-6', '7-9']
for item in j:
if '-' in item:
rng = [int(x) for x in item.split('-')]
else:
# Start and stop are the same
rng = [int(item)] * 2
# Pad the stop number
rng[1] += 1
for i in range(*rng):
print(i)
I would like to start the graph from the first non-zero or non NaN value, also if possible, only connect non-zero/ non NaN terms.
def CreateAvgGraph(input_data):
KK = test3.loc[[input_data],:]
K = KK.T
K = K.fillna(0)
K = K.reset_index()
list1a = K['index'].tolist()
list2a = K[input_data].tolist()
return dcc.Graph(
id='example-graph2',
figure={
'data': [
{'x' : list1a , 'y': list2a, 'type':'line','name' :input_data},
],
'layout': {
'title': str(input_data) + ' Average Price'
}
}
)
[![enter image description here][1]][1]
Removing the fillNa doesn't really help as the view scale is too much.
def CreateAvgGraph(input_data):
KK = test3.loc[[input_data],:]
K = KK.T
K = K.reset_index()
list1a = K['index'].tolist()
list2a = K[input_data].tolist()
return dcc.Graph(
id='example-graph2',
figure={
'data': [
{'x' : list1a , 'y': list2a, 'type':'line','name' :input_data},
],
'layout': {
'title': str(input_data) + ' Average Price'
}
}
)
I have managed to do an ugly fix, but there has to be a better way?
def CreateAvgGraph(input_data):
KK = test3.loc[[input_data],:]
K = KK.T
K = K.fillna(0)
K = K.reset_index()
list1a = K['index'].tolist()
list2a = K[input_data].tolist()
list2aa = []
list1aa =[]
for i in range(0,len(list1a)):
if list2a[i] > 0:
list1aa.append(list1a[i])
list2aa.append(list2a[i])
else:
continue
return dcc.Graph(
id='example-graph2',
figure={
'data': [
{'x' : list1aa , 'y': list2aa, 'type':'line','name' :input_data},
],
'layout': {
'title': str(input_data) + ' Average Price'
If you simply want to plot all non-nan value, you should just drop the nan values rather than filling them with zeros, i.e. you should replace K.fillna(0) with K.dropna().
I'm having issues with a loop that I want to:
a. see if a value in a DF row is greater than a value from a list
b. if it is, concatenate the variable name and the value from the list as a string
c. if it's not, pass until the loop conditions are met.
This is what I've tried.
import pandas as pd
import numpy as np
df = {'level': ['21', '22', '23', '24', '25', '26', '27', '28', '29', '30']
, 'variable':'age'}
df = pd.DataFrame.from_dict(df)
knots = [0, 25]
df.assign(key = np.nan)
for knot in knots:
if df['key'].items == np.nan:
if df['level'].astype('int') > knot:
df['key'] = df['variable']+"_"+knot.astype('str')
else:
pass
else:
pass
However, this only yields the key column to have NaN values. I'm not sure why it's not placing the concatenation.
You can do something like this inside the for loop. No need of any if conditions:
df.loc[df['level'].astype('int') > 25, 'key'] = df.loc[df['level'].astype('int') > 25, 'variable'] + '_' + df.loc[df['level'].astype('int') > 25, 'level']
Lets say I have a time dict
dict = {
'9': {'auth': '9', 'duration': 154.92},
'10': {'auth': '10', 'duration': 132.72},
'4': {'auth': '4', 'duration': 144.59}
}
and how can I get the "rank" value from the dict with a new duration number, lets say 133.92.
It should return dict index 1, since the top list is:
auth-10|duration:132.72
auth-4|duration:144.59
auth-9|duration:154.92
and 133.92 is bigger than 132.72, but less than 144.59 or 154.92
I'm sorry if Its unclear explained, but I tried my best.
EDIT:
I'm trying it again:
I need a function which returns the "predicted/rank" for a custom duration from the sorted list/sorted by "duration/DESC".
So a duration of 160 would return the last place, which is 4. (index+1). A 120 duration should return me the first position which is index 0 or 1st (index+1).
As #MartijnPieters mentioned, dictionaries lack indices, but they do have keys. The following function pred() (short for "predecessor") returns the key of the item whose duration is the largest duration <= the passed duration. It returns None (which can be tested for) if the passed duration is smaller than all of the durations in the dictionary:
from bisect import bisect_left
def pred(duration, entries):
entries = list(entries.items())
entries.sort(key = lambda x: x[1]['duration'])
durations = [x[1]['duration'] for x in entries]
j = bisect_left(durations,duration)
if j == 0:
return None
else:
return entries[j-1][0]
For example, if
d = {
'9': {'auth': '9', 'duration': 154.92},
'10': {'auth': '10', 'duration': 132.72},
'4': {'auth': '4', 'duration': 144.59}
}
(by the way -- don't use dict as an identifier since it has a predefined meaning in Python) then:
>>> pred(133.92,d)
'10'
>>> pred(149.92,d)
'4'
>>> pred(159.92,d)
'9'
>>> pred(129.92,d)
>>>
Note that
>>> pred(129.92,d) == None
True
On Edit: Here is another variation on the same idea, one that returns an integer rank:
def rank(duration, entries):
entries = list(entries.items())
durations = sorted(x[1]['duration'] for x in entries)
return bisect_left(durations,duration)
Then:
>>> rank(133.92,d)
1
>>> rank(129.92,d)
0
Final Edit: At the cost of some readability, here is a 1-liner:
def rank(duration, entries):
return bisect_left(sorted(v['duration'] for v in entries.values()),duration)