Может быть довольно много вещей, которые можно оптимизировать, не связанных с циклом. Например. уменьшение количества итераций приведет к значительному увеличению при наличии, тело внутреннего цикла выполняется 100k * 600k раз, поэтому исключение одной итерации внешнего цикла приведет к удалению 600k итераций внутреннего (или вы можете переключить внутренний и внешний цикл). цикл, если легче удалить итерации из внутреннего цикла)
Единственное, что вы можете сделать в любом случае, это индексировать только один раз для каждой таблицы:
var productNameInfoRows = dsProductNameInfo.Tables[0].Rows
var productInfoCount = productNameInfoRows.Count;
var fullRows = dsFull.Tables[0].Rows;
var fullCount = fullRows.Count;
for (int i = 0; i < productInfoCount; i++)
{
for (int k = 0; k < fullCount; k++)
{
}
}
внутри циклов вы попадете в строки с productNameInfoRows[i]
и FullRows[k]
, что быстрее, чем при использовании длинной руки. Я полагаю, что оптимизация тела может принести больше пользы, чем способ зацикливания. Коллекция. Если, конечно, вы уже не профилировали код и не обнаружили, что фактическое зацикливание является «горлышком бутылки»
РЕДАКТИРОВАТЬ Прочитав ваш комментарий к Марку о том, что вы пытаетесь достичь. Вот как можно это сделать. Стоит отметить, что приведенный ниже алгоритм является вероятностным. То есть есть 1: 2 ^ 32 для двух слов, которые рассматриваются как равные, но на самом деле это не так. Однако это намного быстрее, чем сравнение строк.
Код предполагает, что вы сравниваете первый столбец.
//store all the values that will not change through the execution for faster access
var productNameInfoRows = dsProductNameInfo.Tables[0].Rows;
var fullRows = dsFull.Tables[0].Rows;
var productInfoCount = productNameInfoRows.Count;
var fullCount = fullRows.Count;
var full = new List<int[]>(fullCount);
for (int i = 0; i < productInfoCount; i++){
//we're going to compare has codes and not strings
var prd = productNameInfoRows[i][0].ToString().Split(';')
.Select(s => s.GetHashCode()).OrderBy(t=>t).ToArray();
for (int k = 0; k < fullCount; k++){
//caches the calculation for all subsequent oterations of the outer loop
if (i == 0) {
full.Add(fullRows[k][0].ToString().Split(';')
.Select(s => s.GetHashCode()).OrderBy(t=>t).ToArray());
}
var fl = full[k];
var count = 0;
for(var j = 0;j<fl.Length;j++){
var f = fl[j];
//the values are sorted so we can exit early
for(var m = 0;m<prd.Length && prd[m] <= f;m++){
count += prd[m] == f ? 1 : 0;
}
}
if((double)(fl.Length + prd.Length)/count >= 0.6){
//there's a match
}
}
}
РЕДАКТИРОВАТЬ ваш комментарий побудил меня попробовать еще раз. Код ниже может иметь меньше итераций. Может быть, потому что это зависит от количества совпадений и количества уникальных слов. Множество уникальных слов и множество совпадений для каждого (что потребует много слов в столбце) потенциально приведет к большему количеству итераций. Однако в предположении, что в каждой строке мало слов, это должно привести к значительно меньшему числу итераций. Ваш код имеет сложность N M, это N + M + (соответствует productInfoMatches * fullMatches). Другими словами, последний должен быть почти 99999 * 600k, чтобы иметь больше итераций, чем у вас
//store all the values that will not change through the execution for faster access
var productNameInfoRows = dsProductNameInfo.Tables[0].Rows;
var fullRows = dsFull.Tables[0].Rows;
var productInfoCount = productNameInfoRows.Count;
var fullCount = fullRows.Count;
//Create a list of the words from the product info
var lists = new Dictionary<int, Tuple<List<int>, List<int>>>(productInfoCount*3);
for(var i = 0;i<productInfoCount;i++){
foreach (var token in productNameInfoRows[i][0].ToString().Split(';')
.Select(p => p.GetHashCode())){
if (!lists.ContainsKey(token)){
lists.Add(token, Tuple.Create(new List<int>(), new List<int>()));
}
lists[token].Item1.Add(i);
}
}
//Pair words from full with those from productinfo
for(var i = 0;i<fullCount;i++){
foreach (var token in fullRows[i][0].ToString().Split(';')
.Select(p => p.GetHashCode())){
if (lists.ContainsKey(token)){
lists[token].Item2.Add(i);
}
}
}
//Count all matches for each pair of rows
var counts = new Dictionary<int, Dictionary<int, int>>();
foreach(var key in lists.Keys){
foreach(var p in lists[key].Item1){
if(!counts.ContainsKey(p)){
counts.Add(p,new Dictionary<int, int>());
}
foreach(var f in lists[key].Item2){
var dic = counts[p];
if(!dic.ContainsKey(f)){
dic.Add(f,0);
}
dic[f]++;
}
}
}