В настоящее время у меня есть большой набор данных с разделителями табуляции, который выглядит так (n - это просто число, существует более 4 заголовков), начальный столбец заголовков, который повторяется, за которым следуют не более 2 столбцов данных (иногда только один):
Входной файл:
HDR1 A1 B1
HDR2 A2 B2
HDR3 A3 B3
Hdrn An Bn
HDR1 C1
HDR2 C2
HDR3 C3
Хдрн Сп
HDR1 D1 E1
HDR2 D2 E2
HDR2 D3 E3
хдрн дн эн
Мне нужно транспонировать и преобразовать данные, чтобы вывод выглядел примерно так (поэтому повторяющиеся заголовки удаляются, а данные остаются):
Hdr1 Hdr2 Hdr3 Hdrn
А1 А2 А3 Ан
B1 B2 B3 Bn
C1 C2 C3 Сп
D1 D2 D3 Нн
E1 E2 E3 Ru
Любые идеи о том, как это сделать с помощью оптимизированного макроса javascript EmEditor, будут высоко оценены.
Первый столбец (столбец заголовка) повторяется в источнике тысячи раз, так как записей тысячи. В исходном файле есть не более 2 столбцов данных (после столбца заголовка), но есть также экземпляры, где потенциально может быть только 1 столбец данных, например этот. Я отредактировал исходный пример, чтобы показать это.
Вот макрос JavaScript для вас:
sSeparator = "Hdr1";
sDelimiter = "\t";
sNL = "\r\n";
Redraw = false;
document.CellMode = true; // Must be cell selection mode
editor.ExecuteCommandByID(4323); // Clear All Bookmarks in This Document
document.Filter("^" + sSeparator,0,eeFindReplaceCase | eeFindReplaceRegExp,0,0,0);
editor.ExecuteCommandByID(3927); // Bookmark All
document.Filter("",0,0,0,0,0); // Reset Filter
if ( document.BookmarkCount == 0 ) {
alert( "Cannot find any lines that begin with \"" + sSeparator + "\"" );
Quit();
}
document.selection.StartOfDocument(false);
x1 = 1;
y1 = 1;
nLines = 0;
nMaxCol = document.GetColumns();
str = "";
for( ;; ) {
bStop = false;
if ( document.selection.NextBookmark() ) { // if next bookmark found
y2 = document.selection.GetActivePointY(eePosCellLogical);
}
else {
y2 = document.GetLines(); // if bookmark does NOT exist at end of document
bStop = true;
}
if ( nLines == 0 ) {
nLines = y2 - y1;
}
else {
if ( nLines != y2 - y1 ) {
alert( "Number of lines between " + sSeparator + " is not same. Check the format of the input file." );
Quit();
}
}
for( iCol = x1; iCol <= nMaxCol; ++iCol ) {
s = document.GetCell( y1, iCol, eeCellIncludeQuotes );
if ( s.length == 0 ) {
break;
}
str += s;
str += sDelimiter;
str += document.GetColumn( iCol, sDelimiter, eeCellIncludeQuotes, y1 + 1, y2 - y1 - 1 );
str += sNL;
}
y1 = y2;
if ( bStop ) {
break;
}
x1 = 2; // don't need the first column except the first time
}
editor.NewFile();
document.selection.Text = str; // insert copied text
editor.ExecuteCommandByID(22529); // set TSV mode
Чтобы запустить это, сохраните этот код, например, как Transpose.jsee
, а затем выберите этот файл из Выбирать... в меню Макросы. Наконец, выберите Запустите Transpose.jsee в меню Макросы.
Отлично - спасибо Ютака, работает как положено.
Во входном файле есть только две группы (верхняя половина и нижняя половина, разделенные центральной линией)? Если это так, мы можем упростить задачу.