JavaScript中过滤数组的高效方法

5
以下代码需要花费很长时间才能执行:
var table = new Array();
for(var i =0; i< dtObjects.Rows.length; i++)
        {
            for(var j=0; j< dtColumns.Rows.length; j++)
            {
                for(var k=0; k< dtTypes.Rows.length; k++)
                {
                  if((dtObjects.Rows[i].Id == dtColumns.Rows[j].Id) && (dtColumns.Rows[j].xtype == dtTypes.Rows[k].xtype))  

                      table.push({
                          TableName : dtObjects.Rows[i].Name,
                          Type:  dtObjects.Rows[i].type,
                          ColumName:  dtColumns.Rows[j].Name,
                          DataType: dtTypes.Rows[k].Name,
                          Length : dtColumns.Rows[j].Length
                      });
                }
            }
        }

dtObjects.Rows.length = 900

dtColumns.Rows.length = 1500

dtTypes.Rows.length = 30

有没有办法在几秒钟内实现(过滤)这个?


1
我不知道答案,但我非常期待得到一个答案。 - Qpirate
2
我知道答案,但是我懒得准备示例数据,创建一个fiddle等等 - 这些都是你应该自己完成的事情。 - georg
1
实际上,我正在以低效的方式进行内连接。 - Mehmet Ince
1
准备一些样本数据? - Arun P Johny
1
你是在客户端做这个吗?那不是像 4050 万次操作一样吗? - booyaa
显示剩余6条评论
7个回答

3

没有任何样本数据,我们将无法做出太多贡献,但是抽象地看,这是我可能会考虑一个解决方案的方式。

var table = new Array();

var dtObjectMap = {}, dtColumnMap = {};
for (var i = 0; i < dtObjects.Rows.length; i++) {
    dtObjectMap['id-' + dtObjects.Rows[i].Id] = dtObjects.Rows[i];
}

for (var j = 0; j < dtColumns.Rows.length; j++) {
    if (!dtColumnMap[dtColumns.Rows[j].xtype]) {
        dtColumnMap[dtColumns.Rows[j].xtype] = [];
    }
    dtColumnMap[dtColumns.Rows[j].xtype].push(dtColumns.Rows[j]);
}

var dtObject, dtColumn, dtType, dtCXtypes;
for (var k = 0; k < dtTypes.Rows.length; k++) {
    dtType = dtType.Rows[i], dtCXtypes = dtColumnXtypes[dtType.xtype];
    if (dtCXtypes && dtCXtypes.length) {
        for (var l = 0; l < dtCXtypes.length; l++) {
            dtColumn = dtCXtypes[l];
            dtObject = dtObjectMap['id-' + dtColumn.id];
            if (dtObject) {
                table.push({
                    TableName : dtObject.Name,
                    Type : dtObject.type,
                    ColumName : dtColumn.Name,
                    DataType : dtType.Name,
                    Length : dtColumn.Length
                });
            }
        }
    }
}

1
var table = new Array();
for(var i =0; i< dtObjects.Rows.length; i++)
        {
            for(var j=0; j< dtColumns.Rows.length; j++)
            {
                if(dtObjects.Rows[i].Id == dtColumns.Rows[j].Id){
                    for(var k=0; k< dtTypes.Rows.length; k++)
                {
                  if(dtColumns.Rows[j].xtype == dtTypes.Rows[k].xtype) 

                      table.push({
                          TableName : dtObjects.Rows[i].Name,
                          Type:  dtObjects.Rows[i].type,
                          ColumName:  dtColumns.Rows[j].Name,
                          DataType: dtTypes.Rows[k].Name,
                          Length : dtColumns.Rows[j].Length
                      });
                }

             }

            }
        }

我刚刚在你的最后一个循环之前对你的第一个条件进行了优化,这将使它变得“稍微”快一些。

1

首先,您可以通过id对dtObjects和dtColums进行排序:

function sortById(a,b){
  return (a.id>b.id)?1:(a.id<b.id)?-1:0;
}
dtOjbects.Rows.sort(sortById);
dtColumns.Rows.sort(sortById);

var table = new Array(),
j=0,i=0,
colLen=dtColumns.Rows.length,
objLen=dtObjects.Rows.length,
typLen=dtTypes.Rows.length,
tmpMatch=[];
for(i =0; i< objLen; i++){
  while(j<colLen||dtObjects.Rows[i].id>dtColumns.Rows[j].id){
    if(dtObjects.Rows[i].id===dtColumns.Rows[j].id){
      tmpMatch.push([i,j]);
    }
    j++;
  }
}
for(i=0;i<tmpMatch.length;i++){
  for(j=0;j<typLen;j++){
    if(dtColumns.Rows[tmpMatch[i][1]].xtype == dtTypes.Rows[j].xtype){
      table.push({
        TableName : dtObjects.Rows[tmpMatch[i][0]].Name,
        Type:  dtObjects.Rows[tmpMatch[i][0]].type,
        ColumName:  dtColumns.Rows[tmpMatch[i][1]].Name,
        DataType: dtTypes.Rows[j].Name,
        Length : dtColumns.Rows[tmpMatch[i][1]].Length
    }
  }
}

1
你可以通过使用ID创建索引对象来实现这一点。
var table = new Array(),
    orows = dtObjects.Rows,
    crows = dtColumns.Rows,
    crowsIndex = {},
    types = dtTypes.Rows,
    typesIndex = {};

for (var j = 0; j < crows.length; j++) {
    crowsIndex[crows[j].Id] = crows[j];
}

for (var k = 0; k < types.length; k++) {
    typesIndex[types[k].xtype] = types[k];
}

for (var i = 0; i < orows.length; i++) {
    var rID = orows[i].Id;
    if (crowsIndex[rID]) {
        var xType = crowsIndex[rID].xtype;
        if (typesIndex[xType]) {
            table.push({
                TableName: orows[i].Name,
                Type: orows[i].type,
                ColumName: crowsIndex[rID]].Name,
            DataType: typesIndex[xType].Name,
            Length: crowsIndex[rID].Length
            });
    }
}

这个内容未经测试,可能不是你需要的最终解决方案,但可以帮助你开始。请提供样本数据以进行测试。


1
这与Arun的答案类似(尽管可能更简单)。如果您愿意为了提高速度而牺牲一些内存使用,可以创建对象的哈希值来进行检查。在哈希中检查存在性比迭代每个列、行和类型的ID并进行比较要快得多。为了利用它,您可以先创建类型和列集合的哈希,然后只需在哈希中检查存在性即可。保留html标签。
var table = new Array();
var columnsHash = {};
for(var j=0; j< dtColumns.Rows.length; j++) {
  columnsHash[dtColumns.Rows[j].Id] = dtColumns.Rows[j];
}
var typesHash = {};
for(var k=0; k< dtTypes.Rows.length; k++) {
  typesHash[dtTypes.Rows[k].xtype] = dtTypes.Rows[k];
}

for(var i =0; i< dtObjects.Rows.length; i++) {
  var typesObj, columnObj = columnsHash[dtObjects.Rows[i].Id];
  if (columnObj && (typesObj = typesHash[columnObj.xtype])) {
    table.push({
      TableName : dtObjects.Rows[i].Name,
      Type:  dtObjects.Rows[i].type,
      ColumName:  columnObj.Name,
      DataType: typesObj.Name,
      Length : columnObj.Length
    });
  }
}

注意:我其实还没有测试这段代码,但理论上应该可以工作,除非我漏了什么东西。

1

首先,当你的条件匹配时,你没有放置一个断点。匹配条件后不需要继续执行。

你可以做一件事情。根据你的条件(dtObjects.Rows[i].Id == dtColumns.Rows[j].Id) && (dtColumns.Rows[j].xtype == dtTypes.Rows[k].xtype),我告诉你这个逻辑。

首先循环dtObjects和dtColumns,并检查条件dtObjects.Rows[i].Id == dtColumns.Rows[j].Id。任何id匹配的东西都放在新数组"j值"中(匹配Id时不要忘记放置一个断点)。

完成这个循环后,再取一个循环来处理newArray和dtTypes。按照这种方式检查你的条件"dtColumns[newArray[k]].xtype == dtTypes.Rows[l].xtype"

还有一件事,保持对象作为外部循环,它具有更多的计数。


0

这将大大提高速度。我们需要知道每行可能有多少匹配列。如果只有一个,一旦匹配成功,您也可以中断循环。

var table = new Array();

for(var i =0; i< dtObjects.Rows.length; i++)
    {
        for(var j=0; j< dtColumns.Rows.length; j++)
        {
            if(dtObjects.Rows[i].Id == dtColumns.Rows[j].Id)
            {
                for(var k=0; k< dtTypes.Rows.length; k++)
                {

                    if((dtColumns.Rows[j].xtype == dtTypes.Rows[k].xtype))  {
                          table.push({
                          TableName : dtObjects.Rows[i].Name,
                          Type:  dtObjects.Rows[i].type,
                          ColumName:  dtColumns.Rows[j].Name,
                          DataType: dtTypes.Rows[k].Name,
                          Length : dtColumns.Rows[j].Length
                      });
                        break;
                    }
                }
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接