Home > Blockchain >  Combine two lists in a way that only those elements of first are replaced with elements of second wh
Combine two lists in a way that only those elements of first are replaced with elements of second wh

Time:12-18

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', '-', '-', '-', '-', '-', '-', '-']
# }
  • Related