我已经解析了一个Excel数据网格并构建了一个对象模型。有32列和100,000行。我被要求检查具有重复数据的行并报告它们。对于我的实现,我正在做以下事情:
步骤1需要0.09秒,而剩下的需要花费822秒来处理:/有没有人可以通过更合适的集合或算法来确定我可以在哪里切断?
代码如下:
var results = new Dictionary<string, IList<int>>(numberOfRows);
var hashSet = new HashSet<string>();
var duplicateErrors = new List<string>();
for (var row = firstRow; row <= lastRow; row++)
{
var row1 = row;
taskArray[count++] =
Task<Tuple<int, string>>.Factory.StartNew(() => GetCompleteRowData(row1, tableRawDataHolders));
}
foreach (var task in taskArray)
{
if (hashSet.Add(task.Result.Item2))
{
results.Add(task.Result.Item2, new List<int>() { task.Result.Item1 });
}
else
{
results[task.Result.Item2].Add(task.Result.Item1);
}
}
和
public Tuple<int, string> GetCompleteRowData(int row, IEnumerable<ITableRawDataHolder> tableRawDataHolders)
{
return new Tuple<int, string>(row, string.Join("",
tableRawDataHolders.Where(c => c.Row == row).Select(c => c.Value).ToArray()));
}
和
public class TableRawDataHolder : ITableRawDataHolder
{
public int Row { get; }
public int Column { get; }
public string Value { get; }
public TableRawDataHolder(int row, int column, string value)
{
Row = row;
Column = column;
Value = value;
}
}
答案 0 :(得分:2)
在这种情况下,问题不在于Dictionary或Hashset性能。
开销来自您在GetCompleteRowData中读取数据并处理任务的方式。
为了演示纯哈希集/字典性能,我创建了测试,其中迭代已经准备好的元组数组。这段代码在我的机器上只需32毫秒(i7四核)。
const Int32 numberOfRows = 200000;
var inputData = GetInputData(numberOfRows);
var results = new Dictionary<string, IList<int>>(numberOfRows);
var hashSet = new HashSet<string>();
var sw = Stopwatch.StartNew();
foreach (var dataItem in inputData)
{
if (hashSet.Add(dataItem.Item2))
{
results.Add(dataItem.Item2, new List<int>() {dataItem.Item1});
}
else
{
results[dataItem.Item2].Add(dataItem.Item1);
}
}
Console.WriteLine(sw.ElapsedMilliseconds);
以下是我如何生成测试数据(包括一些实际的重复数据)
private static List<Tuple<int, String>> GetInputData (int numberOfRows)
{
var result = new List<Tuple<int, String>>(numberOfRows);
var rnd = new Random();
for (var i = 0; i < numberOfRows; i++)
{
// Once in 100 records we'll have not unique value
if (result.Count > 0 && rnd.Next(100)%1 == 0)
{
result.Add(new Tuple<int, string>(i, result[rnd.Next(result.Count)].Item2));
}
else
result.Add(new Tuple<int, string>(i, Guid.NewGuid().ToString()));
}
return result;
}