@@ -46,7 +46,7 @@ namespace
4646{
4747
4848
49- struct ThisApplication : Application
49+ struct ThisApplication final : Application
5050{
5151 ThisApplication ()
5252 : Application (" Convert a tsv-file of object-attribute-value triples into a tsv-file with attributes as columns" )
@@ -56,6 +56,8 @@ struct ThisApplication : Application
5656 addPositional (" obj" , " Object column in <table>" );
5757 addPositional (" attr" , " Attribute column in <table>" );
5858 addPositional (" val" , " Value column in <table>" );
59+ addFlag (" no_header" , " .tsv-file has no header" );
60+ addFlag (" aggr" , " Aggregate multipel values" );
5961 }
6062
6163
@@ -66,6 +68,8 @@ struct ThisApplication : Application
6668 const string objName = getArg (" obj" );
6769 const string attrName = getArg (" attr" );
6870 const string valName = getArg (" val" );
71+ const bool headerP = ! getFlag (" no_header" );
72+ const bool aggrP = getFlag (" aggr" );
6973
7074
7175 {
@@ -75,7 +79,9 @@ struct ThisApplication : Application
7579 throw runtime_error (" Oject-attribute-value columns must be different" );
7680 }
7781
78- const TextTable tt (fName );
82+ constexpr size_t displayPeriod = 10000 ; // PAR
83+
84+ const TextTable tt (fName , noString, headerP, displayPeriod);
7985 tt. qc ();
8086
8187 const TextTable::ColNum objCol = tt. col2num (objName);
@@ -113,31 +119,41 @@ struct ThisApplication : Application
113119 }
114120
115121
116- for (const StringVector& row : tt. rows)
117122 {
118- if ( row [objCol]. empty ()
119- || row [attrCol]. empty ()
120- )
121- continue ;
122-
123- ASSERT (contains (obj2num, row [objCol]));
124- const size_t objNum = obj2num [row [objCol]];
125- ASSERT (objNum <= out. rows. size ());
126- if (objNum == out. rows. size ())
123+ Progress prog (tt. rows. size (), displayPeriod);
124+ for (const StringVector& row : tt. rows)
127125 {
128- StringVector newRow (attrs. size () + 1 );
129- newRow [0 ] = row [objCol];
130- out. rows << std::move (newRow);
126+ prog ();
127+
128+ if ( row [objCol]. empty ()
129+ || row [attrCol]. empty ()
130+ )
131+ continue ;
132+
133+ ASSERT (contains (obj2num, row [objCol]));
134+ const size_t objNum = obj2num [row [objCol]];
135+ ASSERT (objNum <= out. rows. size ());
136+ if (objNum == out. rows. size ())
137+ {
138+ StringVector newRow (attrs. size () + 1 );
139+ newRow [0 ] = row [objCol];
140+ out. rows << std::move (newRow);
141+ }
142+
143+ const size_t attrNum = attr2num [row [attrCol]];
144+ ASSERT (attrNum);
145+
146+ string& field = out. rows [objNum] [attrNum];
147+ if (field. empty ())
148+ field = row [valCol];
149+ else
150+ if (aggrP)
151+ aggregate (field, row [valCol], TextTable::aggr_sep);
152+ else
153+ throw runtime_error (" Duplicate object/attribute: " + row [objCol] + " /" + row [attrCol]);
131154 }
132-
133- const size_t attrNum = attr2num [row [attrCol]];
134- ASSERT (attrNum);
135-
136- if (! out. rows [objNum] [attrNum]. empty ())
137- throw runtime_error (" Duplicate object/attribute: " + row [objCol] + " /" + row [attrCol]);
138- out. rows [objNum] [attrNum] = row [valCol];
139155 }
140-
156+
141157
142158 out. saveText (cout);
143159 }
0 commit comments