在 c# 中不使用 for 循环获取单词 table 的单元格索引的最佳方法是什么?
What is the best way to get cell index of a word table without using for loop in c#?
我正在使用 for 循环获取单词 table 的单元格索引,对于更大的 tables 需要花费大量时间,有没有没有 for 循环的方法?
public static int[] GetColumnIndex(Xceed.Words.NET.Table table, string columnName, int endRow,int k)
{
int[] data = { -1, -1 };
for (int j = k; j < endRow; j++)
{
for (int i = 0; i < table.Rows[j].Cells.Count; ++i)
{
if (table.Rows[j].Cells[i].Paragraphs[0].Text.Equals("«" + columnName + "»"))
{
data[0] = j;
data[1] = i;
return data;
}
}
}
return data;
}
我从另一个函数调用这个函数
int startRow = 0, endRow = 0;
int[] ind;
DocX doc;
doc = DocX.Load(fileName);
Xceed.Words.NET.Table t;
t = doc.Tables[0];
endRow = t.Rows.Count;
System.Data.DataTable dt = new DataTable();
dt = reader(report.Query);
foreach (DataColumn col in dt.Columns)
{
ind = GetColumnIndex(t, col.ColumnName, endRow,2);
//...more code here...
}
为了优化您的算法(基于您的访问模式),您可以做一些事情是搜索相同的 table 次(事实上,因为您正在搜索 table,搜索次数随着 table 变大而迅速增加)。因此,值得将 table 中的数据转换为由单词索引的数据结构(例如 Sorted Dictionary)。
首先,创建一个 class 来保存 table 的内容。这样当你想搜索相同的 table 时,你可以使用 class 的相同实例并避免基于排序字典重新创建数据结构:
public class XceedTableAdapter
{
private readonly SortedDictionary<string, (int row, int column)> dict;
public XceedTableAdapter(Xceed.Words.NET.Table table)
{
this.dict = new SortedDictionary<string, (int, int)>();
// Copy the content of the table into the dict.
// If you have duplicate words you need a SortedDictionary<string, List<(int, int)>> type. This is not clear in your question.
for (var i = 0, i < rowCount; i++)
{
for (var j = 0; j < columnCount; j++)
{
// this will overwrite the index if the text was previously found:
this.dict[table.Rows[i].Cells[j].Paragraphs[0].Text] = (i, j);
}
}
}
public (int, int) GetColumnIndex(string searchText)
{
if(this.dict.TryGetValue(searchText, out var index))
{
return index;
}
return (-1, -1);
}
}
现在您只循环整个 table 一次,随后的搜索将在 O(log n) 中进行。如果 Xceed 有一个将数据 table 转换为字典的功能,那将非常方便。我对这个库不熟悉。
现在您可以像这样搜索:
var searchableTable = new XceedTableAdapter(doc.Tables[0]);
foreach (var col in dt.Columns)
{
ind = searchableTable.GetColumnIndex(col);
}
我正在使用 for 循环获取单词 table 的单元格索引,对于更大的 tables 需要花费大量时间,有没有没有 for 循环的方法?
public static int[] GetColumnIndex(Xceed.Words.NET.Table table, string columnName, int endRow,int k)
{
int[] data = { -1, -1 };
for (int j = k; j < endRow; j++)
{
for (int i = 0; i < table.Rows[j].Cells.Count; ++i)
{
if (table.Rows[j].Cells[i].Paragraphs[0].Text.Equals("«" + columnName + "»"))
{
data[0] = j;
data[1] = i;
return data;
}
}
}
return data;
}
我从另一个函数调用这个函数
int startRow = 0, endRow = 0;
int[] ind;
DocX doc;
doc = DocX.Load(fileName);
Xceed.Words.NET.Table t;
t = doc.Tables[0];
endRow = t.Rows.Count;
System.Data.DataTable dt = new DataTable();
dt = reader(report.Query);
foreach (DataColumn col in dt.Columns)
{
ind = GetColumnIndex(t, col.ColumnName, endRow,2);
//...more code here...
}
为了优化您的算法(基于您的访问模式),您可以做一些事情是搜索相同的 table 次(事实上,因为您正在搜索 table,搜索次数随着 table 变大而迅速增加)。因此,值得将 table 中的数据转换为由单词索引的数据结构(例如 Sorted Dictionary)。
首先,创建一个 class 来保存 table 的内容。这样当你想搜索相同的 table 时,你可以使用 class 的相同实例并避免基于排序字典重新创建数据结构:
public class XceedTableAdapter
{
private readonly SortedDictionary<string, (int row, int column)> dict;
public XceedTableAdapter(Xceed.Words.NET.Table table)
{
this.dict = new SortedDictionary<string, (int, int)>();
// Copy the content of the table into the dict.
// If you have duplicate words you need a SortedDictionary<string, List<(int, int)>> type. This is not clear in your question.
for (var i = 0, i < rowCount; i++)
{
for (var j = 0; j < columnCount; j++)
{
// this will overwrite the index if the text was previously found:
this.dict[table.Rows[i].Cells[j].Paragraphs[0].Text] = (i, j);
}
}
}
public (int, int) GetColumnIndex(string searchText)
{
if(this.dict.TryGetValue(searchText, out var index))
{
return index;
}
return (-1, -1);
}
}
现在您只循环整个 table 一次,随后的搜索将在 O(log n) 中进行。如果 Xceed 有一个将数据 table 转换为字典的功能,那将非常方便。我对这个库不熟悉。
现在您可以像这样搜索:
var searchableTable = new XceedTableAdapter(doc.Tables[0]);
foreach (var col in dt.Columns)
{
ind = searchableTable.GetColumnIndex(col);
}