How to fetch data from ImmutableMultiDict in python3 - python-3.x

Hi i am very much new to python programming. Currently i am developing a small application using flask for users to submit data. The form is generated dynamically.I am not using WTForms
Here is the HTML part which is generating the form
{% if message %}
{% for data in message %}
<tr>
<th><input type="text" name="matchnumber" value="{{data.get('matchno')}}" readonly></th>
<th>{{data.get('team1')}}</th>
<th>vs</th>
<th>{{data.get('team2')}}</th>
<th><select name="winner">
<option value="{{data.get('team1')}}">{{data.get('team1')}}</option>
<option value="{{data.get('team2')}}">{{data.get('team2')}}</option>
</select></th>
<th><input type="number" placeholder="Point" name="point" value="{{request.form.point }}" required min="500" max="1000"></th>
</tr>
{% endfor %}
{% endif %}
<table>
the form is getting generated as expected. It will have minimum of 8 columns, it can also be more based on the response it receives from the data base.
But the real problem is arising when I am trying to receive the form data.The data I receive from the form will again be saved in the database
This is the python part from where I am trying to handle the response
result=request.form
result2=result.to_dict(flat=False)
for key,value in result2.items():
print(key,value)
the problem is that the first line is giving a ImmutableMultiDict data and I am not able to iterate through the same and even after converting it to a proper dictionary I am not able to extract each field properly
the result variable is having the output as
ImmutableMultiDict([('matchnumber', '1'), ('matchnumber', '2'), ('matchnumber', '3'), ('matchnumber', '4'), ('matchnumber', '5'), ('matchnumber', '6'), ('matchnumber', '7'), ('matchnumber', '8'), ('winner', 'Russia'), ('winner', 'Egypt'), ('winner', 'Morocco'), ('winner', 'Portugal'), ('winner', 'France'), ('winner', 'Argentina'), ('winner', 'Peru'), ('winner', 'Croatia'), ('point', '800'), ('point', '800'), ('point', '800'), ('point', '800'), ('point', '800'), ('point', '800'), ('point', '800'), ('point', '800')])
after converting it into a dictionary the variable result2 has this as output
{'matchnumber': ['1', '2', '3', '4', '5', '6', '7', '8'], 'winner': ['Russia', 'Egypt', 'Morocco', 'Portugal', 'France', 'Argentina', 'Peru', 'Croatia'], 'point': ['800', '800', '800', '800', '800', '800', '800', '800']}
when i am iterating over the result2 items this is the output that is getting generated
matchnumber ['1', '2', '3', '4', '5', '6', '7', '8']
winner ['Russia', 'Egypt', 'Morocco', 'Portugal', 'France', 'Argentina', 'Peru', 'Croatia']
point ['800', '800', '800', '800', '800', '800', '800', '800']
the exact issue that i am facing is i am not able to iterate over the list simultaneously, i tried googleing and find solutions as to how to fetch exactdata from an ImmutableMultiDic but i didnt get any good result
Please any one can suggest me a better way to get the data out of the form.The entire form is going to be dynamic, as it will change based on the date it will keep updating the match list. I am not using any ORM i am using only raw SQL for processing the data
Thanks in advance

Assuming you want the data in this format:
[{'matchnumber': '1', 'winner': 'Russia', 'point': '800'}, {'matchnumber': '2', 'winner': 'Egypt', 'point': '800'}, ...]
You can try
output = []
for i in range(len(result2['matchnumber'])):
di = {}
for key in result2.keys():
di[key] = result2[key][i]
output.append(di)
print(output)
[{'matchnumber': '1', 'winner': 'Russia', 'point': '800'}, {'matchnumber': '2', 'winner': 'Egypt', 'point': '800'}, {'matchnumber': '3', 'winner': 'Morocco', 'point': '800'}, {'matchnumber': '4', 'winner': 'Portugal', 'point': '800'}, {'matchnumber': '5', 'winner': 'France', 'point': '800'}, {'matchnumber': '6', 'winner': 'Argentina', 'point': '800'}, {'matchnumber': '7', 'winner': 'Peru', 'point': '800'}, {'matchnumber': '8', 'winner': 'Croatia', 'point': '800'}]
Then you can iterate over output and process each dictionary

Unfortunately I can't comment yet, but I wrote the solution by Shivam Singh a bit more compact:
result2 = request.form.to_dict(flat=False)
datamap = [ { key : value[i] for key, value in result.items() } for i in range(len(result['matchnumber'])) ]

Related

Python3 - Issue when appending to list

I'm new to Python and coding in general (so the following code wont be the cleanest) but coming across the following issue that I can't seem to crack:
Problem
I have 2 CSVs which I'm converting to dictionaries and passing to a function one after another, in order to take the dictionary keys and append them to a list outside of the function, I'm having an issue with:
1 - When printing DataList within the function, it returns a result - when I call it from main.py, returns empty list
2 - The ultimate aim is to remove duplicates after collating data into one list (DataList). Within the function, when I'm appending ClearedValues to DataList, since my lists from the CSVs contain 1-6 in first & 1-7 in second, I'd expect the output (after the function has been run twice) to be:
This is the required DataList within function
[['1', '2', '3', '4', '5', '6'], ['1', '2', '3', '4', '5', '6', '7']]
Instead, there is an additional "7" within DataList[0], see output
cleaner.py:
def DictCleaner(dictionary):
CleanedValues.clear()
for k, v in dictionary.items():
if v != None:
CleanedValues.append(v)
DataList.append(CleanedValues)
print(f"This is the CleanedValues {CleanedValues}”)
print(f"This is the DataList inside the function {DataList}")
main.py
loadCSVs("DataSet1.csv")
print(f"This is the main.py DataList list after 1 run {DataList}")
loadCSVs("DataSet2.csv")
print(f"This is the main.py DataList after the 2 runs {DataList}")
Where CleanedValues and DataLists are lists declared within cleaner.py outside of the function scope
& loadCSVs() is the function that reads the CSV, coverts to a dictionary and returns DictCleaner() with the new dictionary as parameter
Output:
This is the CleanedValues [['1', '2', '3', '4', '5', '6']]
This is the DataList inside the function ['1', '2', '3', '4', '5', '6']
This is the main.py DataList list after 1 run [['1', '2', '3', '4', '5', '6']]
This is the CleanedValues ['1', '2', '3', '4', '5', '6', '7']
This is the DataList inside the function [['1', '2', '3', '4', '5', '6', '7'], ['1', '2', '3', '4', '5', '6', '7']]
This is the main.py DataList after the 2 runs [['1', '2', '3', '4', '5', '6', '7']], ['1', '2', '3', '4', '5', '6', '7']]
Expected output:
This is the DataList inside the function [['1', '2', '3', '4', '5', '6']]
This is the CleanedValues ['1', '2', '3', '4', '5', '6']
This is the main.py DataList list after 1 run [['1', '2', '3', '4', '5', '6']]
This is the DataList inside the function [['1', '2', '3', '4', '5', '6'], ['1', '2', '3', '4', '5', '6', '7']]
This is the CleanedValues ['1', '2', '3', '4', '5', '6', '7']
This is the main.py DataList after the 2 runs [['1', '2', '3', '4', '5', '6'], ['1', '2', '3', '4', '5', '6', '7']]
Any suggestions to optimize code or otherwise are greatly appreciated.

How to sort dictionary of list based on certain column?

I have a table like below, stored in a dictionary:
The dictionary looks like this
d = {
'A': ['45', '70', '5', '88', '93', '79', '87', '69'],
'B': ['99', '18', '91', '3', '92', '2', '67', '15'],
'C': ['199200128', '889172415', '221388292', '199200128', '889172415', '889172415', '199200128', '221388292'],
'D': ['10:27:05', '07:10:29', '17:04:48', '10:25:42', '07:11:18', '07:11:37', '10:38:11', '17:08:55'],
'E': ['73', '6', '95', '21', '29', '15', '99', '9']
}
I'd like to sort the dictionary based on the hours from lowest to highest and sum the columns A, B and E corresponding the same value in column C as in image below (where sums of A, B and E are in red):
Then, the resulting dictionary would look like this:
{
'A': ['70', '93', '79', '242', '88', '45', '133', '87', '5', '69', '161'],
'B': ['18', '92', '2', '112', '3', '99', '102', '67', '91', '15', '173'],
'C': ['889172415', '889172415', '889172415', '', '199200128', '199200128', '', '199200128', '221388292', '221388292', ''],
'D': ['07:10:29', '07:11:18', '07:11:37', '', '10:25:42', '10:27:05', '', '10:38:11', '17:04:48', '17:08:55', ''],
'E': ['6', '29', '15', '50', '21', '73', '94', '99', '95', '9', '203']
}
I currently try to sort the input dictionary with this code, but doesn´t seem to work for me.
>>> sorted(d.items(), key=lambda e: e[1][4])
[
('D', ['10:27:05', '07:10:29', '17:04:48', '10:25:42', '07:11:18', '07:11:37', '10:38:11', '17:08:55']),
('E', ['73', '6', '95', '21', '29', '15', '99', '9']),
('C', ['199200128', '889172415', '221388292', '199200128', '889172415', '889172415', '199200128', '221388292']),
('B', ['99', '18', '91', '3', '92', '2', '67', '15']),
('A', ['45', '70', '5', '88', '93', '79', '87', '69'])
]
>>>
May someone give some help with this. Thanks
Do you allow to use pandas to solve this task ?
If yes, then you can transform your data to
pd.DataFrame
object
data = pd.DataFrame.from_dict(dictionary, orient = 'columns')
data = data.sort_values(by =„D”)
And then return to dictionary again using
_dict = data.to_dict()

Remove sequential duplicate word separated by delimiter

I am trying to remove sequential duplicate separated by delimiter '>' from journey column and also aggregate values under column uu and conv. I've tried
INPUT
a=[['journey', 'uu', 'convs'],
['Ct', '10', '2'],
['Ct>Ct', '100', '3'],
['Ct>Pt>Ct', '200', '10'],
['Ct>Pt>Ct>Ct', '40', '5'],
['Ct>Pt>Bu', '1000', '8']]
OUTPUT
a=[['journey', 'uu', 'convs'],
['Ct', '110', '5'],
['Ct>Pt>Ct', '240', '15'],
['Ct>Pt>Bu', '1000', '8']]
I tried below to split but it didn't work
a='>'.join(set(a.split()))
You need to split your string by > and then you could use groupby to eliminate duplicate items in your string. For example:
x = ['Ct>Pt>Ct>Ct', '40', '5']
print(">".join([i for i, _ in groupby(x[0].split(">"))]))
# 'Ct>Pt>Ct'
You could use this as a lambda function in another groupby to aggregate the lists. Then sum each element of the same index by using zip. Check it out:
a=[['journey', 'uu', 'convs'],
['Ct', '10', '2'],
['Ct>Ct', '100', '3'],
['Ct>Pt>Ct', '200', '10'],
['Ct>Pt>Ct>Ct', '40', '5'],
['Ct>Pt>Bu', '1000', '8']]
from itertools import groupby
result = [a[0]] # Add header
groups = groupby(
a[1:],
key=lambda x: ">".join([i for i, _ in groupby(x[0].split(">"))])
)
# groups:
# ['Ct, '[['Ct', '10', '2'], ['Ct>Ct', '100', '3']]]
# ['Ct>Pt>Ct', [['Ct>Pt>Ct', '200', '10'], ['Ct>Pt>Ct>Ct', '40', '5']]]
# ['Ct>Pt>Bu', [['Ct>Pt>Bu', '1000', '8']]]
for key, items in groups:
row = [key]
for i in zip(*items):
if i[0].isdigit():
row.append(str(sum(map(int, i))))
result.append(row)
print(result)
Prints:
[['journey', 'uu', 'convs'],
['Ct', '110', '5'],
['Ct>Pt>Ct', '240', '15'],
['Ct>Pt>Bu', '1000', '8']]

remove multiple rows from a array in python

array([
['192', '895'],
['14', '269'],
['1', '23'],
['1', '23'],
['50', '322'],
['19', '121'],
['17', '112'],
['12', '72'],
['2', '17'],
['5,250', '36,410'],
['2,546', '17,610'],
['882', '6,085'],
['571', '3,659'],
['500', '3,818'],
['458', '3,103'],
['151', '1,150'],
['45', '319'],
['44', '335'],
['30', '184']
])
How can I remove some of the rows and left the array like:
Table3=array([
['192', '895'],
['14', '269'],
['1', '23'],
['50', '322'],
['17', '112'],
['12', '72'],
['2', '17'],
['5,250', '36,410'],
['882', '6,085'],
['571', '3,659'],
['500', '3,818'],
['458', '3,103'],
['45', '319'],
['44', '335'],
['30', '184']
])
I removed the index 2,4,6. I am not sure how should I do it. I have tried few ways, but still can't work.
It seems like you actually deleted indices 2, 5, and 10 (not 2, 4 and 6). To do this you can use np.delete, pass it a list of the indices you want to delete, and apply it along axis=0:
Table3 = np.delete(arr, [[2,5,10]], axis=0)
>>> Table3
array([['192', '895'],
['14', '269'],
['1', '23'],
['50', '322'],
['17', '112'],
['12', '72'],
['2', '17'],
['5,250', '36,410'],
['882', '6,085'],
['571', '3,659'],
['500', '3,818'],
['458', '3,103'],
['151', '1,150'],
['45', '319'],
['44', '335'],
['30', '184']],
dtype='<U6')

update nested list with user input

A function in a program I'm working on takes a list of quiz scores, and asks the user to input the name of a round and the score. If the round already exists, it appends the new score to the existing list, otherwise it adds the round and its score to the top-layer of the list:
lines = [['geography', '8', '4', '7'],
['tv and cinema', '4', '4', '8', '7', '7'],
['all creatures great and small', '7', '8'],
['odd one out', '4', '7'],
['music', '3', '5', '8', '8', '7'],
['how many', '4']]
roundName = input("Enter the name of the round to add: ")
score = input("Enter the score for that round: ")
for line in lines:
if roundName in line:
line.append(score)
lines.append([roundName, score])
#for line in lines:
# if line[0] == roundName.lower().strip():
# existingRound = lines.index(line)
# lines[existingRound].append(score)
# else:
# newRound = [roundName, score]
# lines.append(newRound)
The commented part represents my first few attempts. Entering how many, 3 should result in
lines = [['geography', '8', '4', '7'],
['tv and cinema', '4', '4', '8', '7', '7'],
['all creatures great and small', '7', '8'],
['odd one out', '4', '7'],
['music', '3', '5', '8', '8', '7'],
['how many', '4', '3']]
#actually results, in
[['geography', '8', '4', '7'],
['tv and cinema', '4', '4', '8', '7', '7'],
['all creatures great and small', '7', '8'],
['odd one out', '4', '7'],
['music', '3', '5', '8', '8', '7'],
['how many', '4', '3'],
['how many', '3']]
I can't get the logic in the loop right. Where am I going wrong?
for line in lines:
if roundName in line:
line.append(score)
lines.append([roundName, score])
Right here you're adding the new round to lines regardless of whether if it was present in lines already. Just use a boolean to indicate if adding to lines is needed and then change appending the new round to lines to a conditional:
add = True
for line in lines:
if roundName in line:
line.append(score)
add = False
if add: lines.append([roundName, score])
If order doesn't matter though it would be much easier to use a dictionary:
lines = {'geography':['8', '4', '7'], 'tv and cinema': [...] ...}
roundName = input("Enter the name of the round to add: ")
score = input("Enter the score for that round: ")
if roundName in lines: lines[roundName].append(score)
else: lines[roundName] = [score]

Resources