@@ -690,25 +690,32 @@ def fill_cells(cells: List[dict]) -> List[dict]:
690690 if not cells :
691691 return []
692692
693- table_rows_no = max ({row for cell in cells for row in cell ["row_nums" ]})
694- table_cols_no = max ({col for cell in cells for col in cell ["column_nums" ]})
695- filled = np .zeros ((table_rows_no + 1 , table_cols_no + 1 ), dtype = bool )
693+ # Find max row and col indices
694+ max_row = max (row for cell in cells for row in cell ["row_nums" ])
695+ max_col = max (col for cell in cells for col in cell ["column_nums" ])
696+ filled = set ()
696697 for cell in cells :
697698 for row in cell ["row_nums" ]:
698699 for col in cell ["column_nums" ]:
699- filled [row , col ] = True
700- # add cells for which filled is false
701- header_rows = {row for cell in cells if cell ["column header" ] for row in cell ["row_nums" ]}
700+ filled .add ((row , col ))
701+ header_rows = set ()
702+ for cell in cells :
703+ if cell ["column header" ]:
704+ header_rows .update (cell ["row_nums" ])
705+
706+ # Compose output list directly for speed
702707 new_cells = cells .copy ()
703- not_filled_idx = np .where (filled == False ) # noqa: E712
704- for row , col in zip (not_filled_idx [0 ], not_filled_idx [1 ]):
705- new_cell = {
706- "row_nums" : [row ],
707- "column_nums" : [col ],
708- "cell text" : "" ,
709- "column header" : row in header_rows ,
710- }
711- new_cells .append (new_cell )
708+ for row in range (max_row + 1 ):
709+ for col in range (max_col + 1 ):
710+ if (row , col ) not in filled :
711+ new_cells .append (
712+ {
713+ "row_nums" : [row ],
714+ "column_nums" : [col ],
715+ "cell text" : "" ,
716+ "column header" : row in header_rows ,
717+ }
718+ )
712719 return new_cells
713720
714721
@@ -727,18 +734,20 @@ def cells_to_html(cells: List[dict]) -> str:
727734 Returns:
728735 str: HTML table string
729736 """
730- cells = sorted (fill_cells (cells ), key = lambda k : (min (k ["row_nums" ]), min (k ["column_nums" ])))
737+ # Pre-sort with tuple key, as per original
738+ cells_filled = fill_cells (cells )
739+ cells_sorted = sorted (cells_filled , key = lambda k : (min (k ["row_nums" ]), min (k ["column_nums" ])))
731740
732741 table = ET .Element ("table" )
733742 current_row = - 1
734743
735- table_header = None
736- table_has_header = any (cell ["column header" ] for cell in cells )
737- if table_has_header :
738- table_header = ET .SubElement (table , "thead" )
739-
744+ # Check if any column header exists
745+ table_has_header = any (cell ["column header" ] for cell in cells_sorted )
746+ table_header = ET .SubElement (table , "thead" ) if table_has_header else None
740747 table_body = ET .SubElement (table , "tbody" )
741- for cell in cells :
748+
749+ row = None
750+ for cell in cells_sorted :
742751 this_row = min (cell ["row_nums" ])
743752 attrib = {}
744753 colspan = len (cell ["column_nums" ])
@@ -756,8 +765,9 @@ def cells_to_html(cells: List[dict]) -> str:
756765 table_subelement = table_body
757766 cell_tag = "td"
758767 row = ET .SubElement (table_subelement , "tr" ) # type: ignore
759- tcell = ET .SubElement (row , cell_tag , attrib = attrib )
760- tcell .text = cell ["cell text" ]
768+ if row is not None :
769+ tcell = ET .SubElement (row , cell_tag , attrib = attrib )
770+ tcell .text = cell ["cell text" ]
761771
762772 return str (ET .tostring (table , encoding = "unicode" , short_empty_elements = False ))
763773
0 commit comments