最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Efficient way of filtering arrays in javascript - Stack Overflow

programmeradmin0浏览0评论

Below code takes long lots of minutes;

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

Is there anyway to achieve (filter) this in seconds?

Below code takes long lots of minutes;

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

Is there anyway to achieve (filter) this in seconds?

Share Improve this question asked Jun 6, 2013 at 8:00 Mehmet InceMehmet Ince 4,18914 gold badges47 silver badges65 bronze badges 11
  • 1 i dont know the answer but i am quite interested in an answer. – Qpirate Commented Jun 6, 2013 at 8:03
  • 2 I know the answer, but I'm too lazy to prepare sample data, create a fiddle, etc - something you should have done yourself. – georg Commented Jun 6, 2013 at 8:07
  • 1 no sorting. Actually I am doing inner join in inefficient way. – Mehmet Ince Commented Jun 6, 2013 at 8:11
  • 1 prepare some sample data? – Arun P Johny Commented Jun 6, 2013 at 8:11
  • 1 you're doing this client side? isn't that like 40.5 million ops? – booyaa Commented Jun 6, 2013 at 8:16
 |  Show 6 more ments

7 Answers 7

Reset to default 3

With out any sample data we won't able to do much, but in an abstract this is how I might look at a solution

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
                });
            }
        }
    }
}

First of all you did not put a break when your condition matches. there is no need to go continue after matching condition.

You can do one thing. As per your condition (dtObjects.Rows[i].Id == dtColumns.Rows[j].Id) && (dtColumns.Rows[j].xtype == dtTypes.Rows[k].xtype) I am telling you this logic.

First loop dtObjects and dtColumns and check for condtion dtObjects.Rows[i].Id == dtColumns.Rows[j].Id. Whatever id's are matching put that "j value" new array (do not forget to put a break when Id match).

Once you done with this loop. Take one more loop for newArray and dtTypes. Check your condition in this manner "dtColumns[newArray[k]].xtype == dtTypes.Rows[l].xtype"

One more thing, keep the object as a outer loop who has more count.

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
                      });
                }

             }

            }
        }

I just conditioned your first condition before your last loop this will make it "little bit" faster

First you can sort both dtObjects and dtColums by id:

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
    }
  }
}

You can do this by creating index object using 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
            });
    }
}

This is NOT TESTED and may not be the final solution you need, but will help you to get started. Please provide sample data to test.

This is similar to Arun's answer (albeit maybe simpler).

What you can do if you are willing to trade a little more memory use for increased speed, is creating a hash of the objects that you will be checking against.

Checking existence in a hash is considerably faster that iterating through and paring Ids for each column, row & type. To take advantage of that you can start by creating a hash of both of the types and the columns collections, then you only have to check for existence within the hash.

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
    });
  }
}

Note: I haven't actually tested the code, obviously, but in theory this should work, unless I'm missing something.

This will give considerable speed. We need to know how many matching column possible for each row. If it is just one you can break the loop also once matched.

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;
                    }
                }
            }
        }
    }
发布评论

评论列表(0)

  1. 暂无评论