I want to join two lists in a way that only those elements of first are replaced with elements of second which are different from each other.
[
['19-12-2022', 'MATH161: A', '-', '-', '-', '-', '-', '-', '-'],
['19-12-2022', '-', 'MATH111: P', '-', '-', '-', '-', '-', '-'],
['19-12-2022', '-', '-', 'HU108: P', '-', '-', '-', '-', '-'],
['21-12-2022', 'CS110lab: P', '-', '-', '-', '-', '-', '-', '-']
]
This is the list of lists. I want to combine them such that those which have the same date are combined into a single list.
def getAttendanceTableFor(id: str) -> pd.DataFrame:
"""This function takes a student's cms Id, then creates a table for his attendance in all courses and returns it as a DataFrame object.
Args:
id (str): Id of student
Returns:
pd.DataFrame: DataFrame object for attendance of student.
"""
db = sqlite3.connect(databaseName)
cur = db.cursor()
tableOfAttendance = []
timeTableWeekDays = timeTable.to_dict('tight')['index']
timeTableTimes = timeTable.to_dict('tight')['columns']
timeTableClasses = timeTable.to_dict('tight')['data']
for course in courses:
cur.execute(f"SELECT `dayTime`, `{id}` FROM `{course}`;")
records = cur.fetchall()
# dayTime is in form of date-month-year-time
# So first 3 are date and last one is time
dates = list(["-".join(date.split('-')[:3])
for date, _ in records])
times = list([date.split('-')[-1]
for date, _ in records])
attendances = list([attendance
for _, attendance in records])
for time in times:
if len(time) == 3:
times[times.index(time)] = '0' time
for date in dates:
record = [date] ["-"] * len(
timeTableTimes)
for time, attendance in zip(times, attendances):
weekDayIndex = timeTableWeekDays.index(getWeekDay(date))
timeIndex = timeTableTimes.index(time)
record[timeIndex
1] = f"{timeTableClasses[weekDayIndex][timeIndex]}: {attendance}"
tableOfAttendance.append(record)
[print(d) for d in tableOfAttendance]
cur.close()
db.close()
attendanceDataFrame = pd.DataFrame(tableOfAttendance,
columns=(['Date'] timeTableTimes))
return attendanceDataFrame
This is the code that I wrote to generate that list of lists.
CodePudding user response:
You can try:
lst = [
["19-12-2022", "MATH161: A", "-", "-", "-", "-", "-", "-", "-"],
["19-12-2022", "-", "MATH111: P", "-", "-", "-", "-", "-", "-"],
["19-12-2022", "-", "-", "HU108: P", "-", "-", "-", "-", "-"],
["21-12-2022", "CS110lab: P", "-", "-", "-", "-", "-", "-", "-"],
]
tmp = {}
for subl in lst:
tmp.setdefault(subl[0], []).append(subl[1:])
out = []
for k, v in tmp.items():
out.append([k])
for t in zip(*v):
out[-1].append(next((i for i in t if i != "-"), "-"))
print(out)
Prints:
[
["19-12-2022", "MATH161: A", "MATH111: P", "HU108: P", "-", "-", "-", "-", "-"],
["21-12-2022", "CS110lab: P", "-", "-", "-", "-", "-", "-", "-"],
]
CodePudding user response:
My suggestion is to use itertools.groupby
to group based on date:
from itertools import groupby
from operator import itemgetter
data = [
['19-12-2022', 'MATH161: A', '-', '-', '-', '-', '-', '-', '-'],
['19-12-2022', '-', 'MATH111: P', '-', '-', '-', '-', '-', '-'],
['19-12-2022', '-', '-', 'HU108: P', '-', '-', '-', '-', '-'],
['21-12-2022', 'CS110lab: P', '-', '-', '-', '-', '-', '-', '-']
]
s = sorted(data, key=itemgetter(0))
g = groupby(data, key=itemgetter(0))
d = {k: list(v) for k, v in g}
# {
# '19-12-2022': [
# ['19-12-2022', 'MATH161: A', '-', '-', '-', '-', '-', '-', '-'],
# ['19-12-2022', '-', 'MATH111: P', '-', '-', '-', '-', '-', '-'],
# ['19-12-2022', '-', '-', 'HU108: P', '-', '-', '-', '-', '-']],
# '21-12-2022': [
# ['21-12-2022', 'CS110lab: P', '-', '-', '-', '-', '-', '-', '-']
# ]
# }
Now making use of functools.reduce
to replace the contents of the lists.
from functools import reduce
{
k: reduce(lambda acc, x: [a if b == '-' else b for a, b in zip(acc, x)], v[1:], v[0])
for k, v in d.items()
}
# {
# '19-12-2022': ['19-12-2022', 'MATH161: A', 'MATH111: P', 'HU108: P', '-', '-', '-', '-', '-'],
# '21-12-2022': ['21-12-2022', 'CS110lab: P', '-', '-', '-', '-', '-', '-', '-']
# }