These are previously defined.
def get_service_code(service):
return str(service[0])
service_106_data = filter_routes(bus_stations, "106") #[('106', '1', '1', '43009'), ('106', '1', '2', '43179'), .... ('106', '2', '51', '43009')]
service_106 = make_service(service_106_data, "106") # ('106', [['43009', '43179',...'43009']])
print(get_service_code(service_106)) --> should return 106
bus_stations here is a txt file that contain a list of numbers like this
106,1,1,43009
106,1,2,43179
.
.
.
106,2,1,03239
106,2,2,03211
.
.
.
106,2,50,43171
106,2,51,43009
Then this is also previously defined
def get_route(service, direction):
return str(service[int(direction)][0])
print(get_route(service_106, '1'))
should return this
['43009', '43179', '43189', '43619', '43629', '42319', '28109', '28189', '28019', '20109', '17189', '17179', '17169', '17159', '19049', '19039', '19029', '19019', '11199', '11189', '11401', '11239', '11229', '11219', '11209', '13029', '13019', '09149', '09159', '09169', '09179', '09048', '09038', '08138', '08057', '08069', '04179', '02049', 'E0200', '02151', '02161', '02171', '03509', '03519', '03539', '03129', '03218', '03219']
def make_service(service_data, service_code):
routes = []
curr_route = []
first = service_data[0] #('106', '1', '1', '43009')
curr_dir = first[1] # '1'
l = list(curr_dir) # ['1']
for entry in service_data:
direction = entry[1] #'1'
stop = entry[3] #'43009'
if direction == curr_dir:
curr_route.append(stop) #[43009]
else:
routes.append(curr_route) #[[]]
curr_route = [stop] #['43009']
curr_dir = direction #not '1'
l.append(list(direction)) # ['1', __]
routes.append(curr_route) #[['43009']]
#modify this code below
return (service_code,curr_route) #("106", [['43009']])
service_106 = make_service(service_106_data, "106")
print(service_106)
print(get_service_code((service_106))) # should return 106
expected output for print(service_106) is
('106',['1','2'],['03239', '03211', 'E0321', 'E0564', '03222', 'E0599', '03531', '03511', '03501', '02051', '02061', '04111', '04121', '08041', '08031', '08111', '08121', '09059', '09022', '09111', '09121', '09131', '09141', '13011', '13021', '11201', '11211', '11221', '11231', '11419', '11409', '11181', '11191', '19011', '19021', '19031', '19041', '17151', '17161', '17171', '17181', '20101', '28011', '28181', '28101', '42311', '43621', '43611', '43181', '43171', '43009'])
Where ['1','2'] suppose to be the newly added list also not only should i be able to add ['1','2'] I should be able to add ['A4'] / ['A2','A4'] or other non-numeric list in as well
I am only suppose to add new lines to the code and modify the last line.
I suppose you can use:
return tuple([service_code] + service_data)
I think you just need
return (service_code, list(set(zip(*service_data)[1])), curr_route) #("106", [['43009']])
its very hard to tell though(but this does give the expected output)
using
make_service([('106', '1', '1', '43009'), ('106', '1', '2', '43179'), ('106', '2', '51', '43009')],"106")
results in ('106', ['1', '2'], ['43009'])
Related
I have a .txt file that contains elements that look like this:
Smith 25 35 NC
Johnson 12 4 OH
Jones 23 14 FL
Lopez 2 7 TX
And I want to read the .txt file line by line, and save each of the elements (Name, number, number, state) in an array matrix or a list 4 x number_of_people , while ignoring any blank spaces. I'm trying to not use split() for it, but could use a "manual" form of split() instead, like shown below with split1.
def split1(line,delim):
s=[]
j=0
for i in range (len(line)):
if delim== line [i]:
s.append(line[j:i])
j=i+1
s.append (line[j:])
return s
f = open("Names.txt")
number_of_people = 0
#This portion is meant to go through the entire .txt file, 1 time and count how many people are listed on the file so I can make an appropiatly sized matrix, in the case of the example is 4
while True:
file_eof = f.readline()
if file_eof != '':
number_of_people = number_of_people + 1
if file_eof == '':
break
#This portion reads through the .txt file agin and saves the names of the list
while True:
file_eof = f.readline()
if file_eof != '':
split1(file_eof, '')
#print(file_eof)
if file_eof == '':
print('No more names on the list')
break
f.close()
I know there could be things missing here, and that's exactly what I would need help with here. If there is any "better" way of dealing with this than what I got please let me know and show me if possible.
Thank you for your time!
I don't understand why you want to create an array of a specific size first. I suppose you have a background in C? How large is the file?
Here are 2 pythonic ways to read and store that information:
filename = r"data.txt"
# Access items by index, e.g. people_as_list[0][0] is "Smith"
with open(filename) as f: # with statement = context manager = implicit/automatic closing of the file
people_as_list = [line.split() for line in f] # List comprehension
# Access items by index, then key, e.g. people_as_dict[0]["name"] is "Smith"
people_as_dict = []
with open(filename) as f:
for line in f:
name, number1, number2, state = line.split() # Iterable unpacking
person = {}
person["name"] = name
person["number1"] = number1
person["number2"] = number2
person["state"] = state
people_as_dict.append(person)
print(people_as_list)
print(people_as_dict)
Output:
[['Smith', '25', '35', 'NC'], ['Johnson', '12', '4', 'OH'], ['Jones', '23', '14', 'FL'], ['Lopez', '2', '7', 'TX']]
[{'name': 'Smith', 'number1': '25', 'number2': '35', 'state': 'NC'}, {'name': 'Johnson', 'number1': '12', 'number2': '4', 'state': 'OH'}, {'name': 'Jones', 'number1': '23', 'number2': '14', 'state': 'FL'}, {'name': 'Lopez', 'number1': '2', 'number2': '7', 'state': 'TX'}]
match_records = soup.find_all('td',class_ = 'rankings-block__banner--matches')
match_records
records = []
for i in match_records:
records.append(i.text)
records
match_records2 = soup.find_all('td',class_ = 'table-body__cell u-center-text')
match_records2
for i in match_records2:
records.append(i.text)
print(records)
output:-
['17', '32', '3,793', '28', '3,244', '32', '3,624', '25', '2,459', '27', '2,524', '30', '2,740', '30', '2,523', '32', '2,657', '17', '1,054', '7', '336', '25', '1,145', '11', '435', '20', '764', '7', '258', '11', '330', '9', '190', '14', '232', '6', '97', '9', '0']
At the end of your code the variable records holds a list of strings.
You can either add 'if' statements when filling it, to ensure only 50+ values get in, or, you can analyze the list after filling it.
Notice the difference between str and int objects, and notice the commas , (see 1,234) you'll need to get rid off.
I'd add the following snippet after your code:
fixed_records = [int(record.replace(',','')) for record in records]
This will create the wanted list.
Note that this is not the most efficient (memory + time), but it is simple to use and understand.
You can easily do this with the help of lambda expression and filter.
records = list(filter(lambda a: int(a.replace(',', '')) < 50, records))
Do you need string again?
Use an if statement:
match_records = soup.find_all('td',class_ = 'rankings-block__banner--matches')
match_records
records = []
for i in match_records:
if (a:=int(i.text.replace(',', '')) < 50:
records.append(a)
print(records)
match_records2 = soup.find_all('td',class_ = 'table-body__cell u-center-text')
match_records2
for i in match_records2:
if (a:=int(i.text.replace(',', '')) < 50:
records.append(a)
print(records)
With the walrus operator. If your Python version is under 3.8, use:
match_records = soup.find_all('td',class_ = 'rankings-block__banner--matches')
match_records
records = []
for i in match_records:
a = int(i.text.replace(',', ''))
if a < 50:
records.append(a)
print(records)
match_records2 = soup.find_all('td',class_ = 'table-body__cell u-center-text')
match_records2
for i in match_records2:
a = int(i.text.replace(',', ''))
if a < 50:
records.append(a)
print(records)
I have a programme that reads a list of lists and produces a key from the first element in each list and a value from the other elements in the list. If the key already exists then the programme appends the list data to the existing value in the dictionary pair.
My code looks like:
# IMPORTS
from csv import reader
# VARIABLES
test_list = [['\ufeffCategory', 'materials', 'details', 'cost'], ['Clothes', 'Socks', 'Wool', '5'], ['Clothes', 'Shorts', 'Cotton', '5'], ['Clothes', 'Trousers', 'Cotton', '15'], ['Education', 'Books', 'Rymans', '10'], ['Education', 'Pens', 'Rymans', '12'], ['Education', 'Pencils', 'Rymans', '4'], ['Education', 'Paper', 'WH Smths', '3.5'], ['Education', 'computer', 'PC World', '800'], ['Entertainment', 'Kindle Unlimited', 'DD', '7.99'], ['Entertainment', 'Audible', 'On hold', '7'], ['Entertainment', 'Spotify', 'DD', '11.99'], ['Entertainment', 'Netflix', 'DD', '9']]
def make_dict_from_csv(test_list):
""" read list make a key:value pair making the key the first element in list and the rest of the elements as the value"""
budget_dict = {}
i = 0
starting_key = ""
temp_list = []
for item in test_list:
key = test_list[i][0]
if key != starting_key:
value = [n for n in test_list[i][1:]]
budget_dict[key] = value
starting_key = key
value = []
else:
value = []
value = [n for n in test_list[i][1:]]
temp_list = []
for k, v in budget_dict.items():
if k == starting_key:
temp_list = [v, value]
budget_dict[key] = temp_list
temp_list = []
i += 1
del budget_dict["\ufeffCategory"] # delete header data
return budget_dict
budget_list = read_csv_make_list(file)
budget_dict = make_dict_from_csv(test_list)
print(budget_dict)
How can I 'flatten' the lists in the key:value pair so that I end up with e.g.
{'Clothes': [['Socks', 'Wool', '5'], ['Shorts', 'Cotton', '5'], ['Trousers', 'Cotton', '15']]}
rather than
{'Clothes': [[['Socks', 'Wool', '5'], ['Shorts', 'Cotton', '5']], ['Trousers', 'Cotton', '15']]}`
?
Try this:
def make_dict_from_csv(test_list):
budget_dict = dict()
for sublist in test_list:
key = sublist[0]
if key=="\ufeffCategory":
continue
if key in budget_dict:
budget_dict[key].append(sublist[1:])
else:
budget_dict[key] = [sublist[1:]]
return budget_dict
>>> make_dict_from_csv(test_list)
{'Clothes': [['Socks', 'Wool', '5'],
['Shorts', 'Cotton', '5'],
['Trousers', 'Cotton', '15']],
'Education': [['Books', 'Rymans', '10'],
['Pens', 'Rymans', '12'],
['Pencils', 'Rymans', '4'],
['Paper', 'WH Smths', '3.5'],
['computer', 'PC World', '800']],
'Entertainment': [['Kindle Unlimited', 'DD', '7.99'],
['Audible', 'On hold', '7'],
['Spotify', 'DD', '11.99'],
['Netflix', 'DD', '9']]
}
def make_dict_from_csv(test_list):
ret = {}
for i in range(1,len(test_list)):
key = test_list[i][0]
value = test_list[i][1:]
if key not in ret:
ret[key] = [value]
else:
ret[key].append(value)
return ret
You can condense this greatly.
from collections import defaultdict
def make_dict_from_csv(test_list):
itr = iter(test_list)
next(itr) # Skip the header
budget_dict = defaultdict(list)
for key, *value in itr:
budget_dict[key].append(value)
return budget_dict
I have some arrays with the same customer names on different orders, what I am trying to do and the following:
1 - Take the name of customers and compare to return when it is the same, solving the problem of random order;
2 - After obtaining this comparison, the output should be as follows:
The solution below resolves if I use the arrays manually, but when I enter through the database, I have an error as output
It works:
array1 = [['CLIENT1', '2', '3'],['CLIENT2', '3', '4'],['CLIENT3', '4', '5']]
array2 = [['CLIENT3', '2', '3'],['CLIENT2', '3', '4'],['CLIENT1', '4', '5']]
array3 = [['CLIENT2', '2', '3'],['CLIENT1', '3', '4'],['CLIENT3', '4', '5']]
The output should look like this: Customer Name, value contained in array1 for this customer name, value contained in array2 for this customer name and value contained in array3 for this customer name
SCRIPT
#!/usr/bin/python
# -*- coding: utf-8 -*-
import psycopg2
from datetime import datetime, date, time, timedelta
# create script head
print ('----------------------------------------------------------------------------')
print ('Initializing script: '+str(date.today()))
print ('----------------------------------------------------------------------------')
################################################################################
# Set connection to postgres
connpostgres = psycopg2.connect("host='192.168.0.245'"
" dbname='metrics'"
" user='postgres'"
" password=pass123")
cursorpost = connpostgres.cursor()
################################################################################
# Create arrays
################################################################################
cursorpost.execute(rz_collect)
rz_collect = cursorpost.fetchall()
array_rz_collect = []
for row in rz_collect:
array_rz_collect.append(row)
cursorpost.execute(sql_on_off)
sql_on_off = cursorpost.fetchall()
array_sql_on_off = []
for row in sql_on_off:
array_sql_on_off.append(row)
cursorpost.execute(sql_gaps_so)
sql_gaps_so = cursorpost.fetchall()
array_sql_gaps_so = []
for row in sql_gaps_so:
array_sql_gaps_so.append(row)
cursorpost.execute(sql_gaps_db)
sql_gaps_db = cursorpost.fetchall()
array_sql_gaps_db = []
for row in sql_gaps_db:
array_sql_gaps_db.append(row)
cursorpost.execute(sql_gaps_sap)
sql_gaps_sap = cursorpost.fetchall()
array_sql_gaps_sap = []
for row in sql_gaps_sap:
array_sql_gaps_sap.append(row)
################################################################################
# Check and align arrays
# Initialize a dictionary with key = client name, value = list of client entries
result = {}
# Add values from array1
for client_info in array_rz_collect:
# Parse current entry
client_name = client_info[0]
client_values = client_info[1:]
print(client_values)
# Add previous values if exitant
if client_name in result.keys():
client_values.extend(result[client_name])
# Update clients dictionary
result[client_name] = client_values
# Add values from array2
for client_info in array_sql_on_off:
# Parse current entry
client_name = client_info[0]
client_values = client_info[1:]
# Add previous values if exitant
if client_name in result.keys():
client_values.extend(result[client_name])
# Update clients dictionary
result[client_name] = client_values
# Add values from array3
for client_info in array_sql_gaps_so:
# Parse current entry
client_name = client_info[0]
client_values = client_info[1:]
# Add previous values if exitant
if client_name in result.keys():
client_values.extend(result[client_name])
# Update clients dictionary
result[client_name] = client_values
# Print result information
for client_name, client_values in result.items():
print("Result: " + str(client_name) + ", " + str(client_values))
OUTPUT
File "SCRIPT.py", line 166, in <module>
client_values.extend(result[client_name])
AttributeError: 'tuple' object has no attribute 'extend'
DESERIED OUTPUT
Result: CLIENT1, ['3', '4', '4', '5', '2', '3']
Result: CLIENT2, ['2', '3', '3', '4', '3', '4']
Result: CLIENT3, ['4', '5', '2', '3', '4', '5']
The output of cursorpost.fetchall() (rz_collect) is a list of tuples.
In the code,
rz_collect = cursorpost.fetchall()
array_rz_collect = []
for row in rz_collect:
array_rz_collect.append(row)
array_rz_collect is same as rz_collect, therefore it too is a list of tuples.
Side note: That for loop is unnecessary, you can directly operate on rz_collect
In the code,
for client_info in array_rz_collect:
# Parse current entry
client_name = client_info[0]
client_values = client_info[1:]
print(client_values)
# Add previous values if exitant
if client_name in result.keys():
client_values.extend(result[client_name])
client_info is a tuple.
client_values is also a tuple since you are just slicing another tuple. Tuples do not have the extend method since they are not mutable like lists.
A simple fix to your problem is to convert the tuple to list.
client_info = list(client_info) # new line
client_name = client_info[0]
client_values = client_info[1:]
What I am trying to accomplish is printing 10 lines only instead of the whole list using pprint(dict(str_types))
Here is my code
from collections import defaultdict
str_type_re = re.compile(r'\b\S+\.?$', re.IGNORECASE)
expected = ["Street", "Avenue", "Boulevard", "Drive", "Court", "Place", "Square", "Lane", "Road",
"Trail", "Parkway", "Commons"]
def audit_str_type(str_types, str_name, rex):
stn = rex.search(str_name)
if stn :
str_type = stn.group()
if str_type not in expected:
str_types[str_type].add(str_name)
I defined a function that audits tag elements where k="addr:street", and also any tag elements match the is_str_name function.
def audit(osmfile,rex):
osm_file = open(osmfile, "r", encoding="utf8")
str_types = defaultdict(set)
for event, elem in ET.iterparse(osm_file, events=("start",)):
if elem.tag == "node" or elem.tag == "way":
for tag in elem.iter("tag"):
if is_str_name(tag):
audit_str_type(str_types, tag.attrib['v'],rex)
return str_types
In the code above , I used "is_str_name" function to filter tag when calling the audit function to audit street names.
def is_str_name(elem):
return (elem.attrib['k'] == "addr:street")
str_types = audit(mydata, rex = str_type_re)
pprint.pprint(dict(str_types[:10]))
Use pprint.pformat to get back the string representation of the object instead of printing it directly, then you can split it up by lines and only print out the first few:
whole_repr = pprint.pformat(dict(str_types))
for line in whole_repr.splitlines()[:10]:
print(line)
Note that I couldn't test this since you did not have a MCVE but I did verify it with a more trivial example:
>>> import pprint
>>> thing = pprint.pformat({i:str(i) for i in range(10000)})
>>> type(thing), len(thing)
(<class 'str'>, 147779)
>>> for line in thing.splitlines()[:10]:print(line)
{0: '0',
1: '1',
2: '2',
3: '3',
4: '4',
5: '5',
6: '6',
7: '7',
8: '8',
9: '9',