重构两个$ .each()循环到一个

时间:2015-04-19 06:17:15

标签: javascript jquery json

我有一个像这样的JSON对象......

{  
   "tasks":[  
      {  
         "id":"task_3",
         "taskName":"Task A",
         "assignee":"Barrack Obama",
         "timeReqOptimisitic":"4",
         "timeReqNormal":"8",
         "timeReqPessimistic":"14",
         "timeUnit":"Days",
         "timeReq":"8.33",
         "positionX":493,
         "positionY":101,
         "lockStatus":"unlocked"
      }
   ],
   "milestones":[  
      {  
         "id":"task_1",
         "milestoneName":"Start",
         "positionX":149,
         "positionY":109,
         "lockStatus":"unlocked",
         "milestoneDate":"2015-04-07"
      },
      {  
         "id":"task_2",
         "milestoneName":"Finish",
         "positionX":989,
         "positionY":367,
         "lockStatus":"unlocked",
         "milestoneDate":"2015-04-22"
      }
   ],
   "connections":[  
      {  
         "connectionId":"con_10",
         "pageSourceId":"task_1",
         "pageTargetId":"task_3"
      },
      {  
         "connectionId":"con_20",
         "pageSourceId":"task_3",
         "pageTargetId":"task_2"
      }
   ]
}

...这是一个最小版本。在实践中,“任务”,“里程碑”和“连接”中有许多项目。

我需要遍历对象并确定具有最低/最早“milestoneDate”的“里程碑”项的“id”,然后标识“connectionsSourceId”具有相同值的“connections”项并返回它的“pageTargetId”。

所以在上面的例子中:

步骤1)遍历对象并确定具有最低/最早“milestoneDate”的“里程碑”项目的“id”。

Answer: milestones.id = "task_1"

步骤2)识别“connectionSourceId”具有相同值的“connections”项。

Answer: connections.pageSourceId = "task_1"

步骤3)返回其“pageTargetId”。

Answer: "task_3"

我有一个工作示例here。但是,我想知道是否有办法在不使用极高的开始日期和一个循环的情况下完成此任务。

3 个答案:

答案 0 :(得分:1)

由于您没有在这两个循环上解析相同的数组,因此无法合并您的循环。

无论如何,你可以删除循环来访问数组:

http://jsfiddle.net/gael/sruvtwre/2/

$.each(object.milestones, function( index, value ) {
    if(startDate > parseDate(value.milestoneDate)) {
        startDate = parseDate(value.milestoneDate);
        id = value.id
    }  
});

$.each(object.connections, function( index, value ) {
    if(id == value.pageSourceId) {
        pageTargetId = value.pageTargetId;                
    }
});

也可以对数据进行排序和索引。那你就不需要循环了:

里程碑中的元素应该排序,因此最早的里程碑元素将是里程碑[0]。

连接中的元素应该由其pageTargetId属性建立索引,因此请求的元素应该是connections [id]。

你的两个循环将成为:

var pageTargetId= object.connections[ object.milestones[0].id ].pageTargetId;

http://jsfiddle.net/gael/sruvtwre/4/

如评论中所述,排序不是最佳解决方案,即使这对于小集合并不重要。 粗略地说,没有必要对所有数据进行排序,只需要对最新事项进行排序。

您可以使用array reduce method作为简单循环的替代方案:

var latestMilestone= object.milestones.reduce(function(milestone1, milestone2){

    if( parseDate(milestone1.milestoneDate) > parseDate(milestone2.milestoneDate) )
        return milestone1;
    else
        return milestone2;

    //convert date to timestamp
    function parseDate(date) {
        var parts = date.split('-');
        return Date.UTC(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
    }

});

答案 1 :(得分:0)

这个怎么样:

假设你在第一个循环中得到milestones.id = "task_1";在循环之外我们可以使用jQuery grep。由于connections将具有唯一pageSourceId,因此grep将返回仅包含一个对象的数组。

var filteredData = jQuery.grep('CONNECTIONS_ARRAY', function(element, index){
     return element.pageSourceId == 'MILESTONES_ID'; // Which you get in the loop earlier
});

然后我们可以像这样访问pageTargetId

if(filteredData.length){    
  filteredData[0].pageTargetId;
}

答案 2 :(得分:0)

尝试

var dates = []
, ids = []
, filtered = $.map(data.milestones, function(value, index) {
    dates.push(new Date(value.milestoneDate).getTime());
    ids.push(value.id);
    if (dates.length === data.milestones.length) {
      var id = ids[$.inArray(Math.min.apply(Math, dates), dates)]
      , res = $.grep(data.connections, function(task, key) {
        return task.pageSourceId === id
      })[0].pageTargetId;
      return res
    }
  })[0]; // `"task_3"`



var data = {  
   "tasks":[  
      {  
         "id":"task_3",
         "taskName":"Task A",
         "assignee":"Barrack Obama",
         "timeReqOptimisitic":"4",
         "timeReqNormal":"8",
         "timeReqPessimistic":"14",
         "timeUnit":"Days",
         "timeReq":"8.33",
         "positionX":493,
         "positionY":101,
         "lockStatus":"unlocked"
      }
   ],
   "milestones":[  
      {  
         "id":"task_1",
         "milestoneName":"Start",
         "positionX":149,
         "positionY":109,
         "lockStatus":"unlocked",
         "milestoneDate":"2015-04-07"
      },
      {  
         "id":"task_2",
         "milestoneName":"Finish",
         "positionX":989,
         "positionY":367,
         "lockStatus":"unlocked",
         "milestoneDate":"2015-04-22"
      }
   ],
   "connections":[  
      {  
         "connectionId":"con_10",
         "pageSourceId":"task_1",
         "pageTargetId":"task_3"
      },
      {  
         "connectionId":"con_20",
         "pageSourceId":"task_3",
         "pageTargetId":"task_2"
      }
   ]
};

    var dates = []
    , ids = []
    , filtered = $.map(data.milestones, function(value, index) {
      dates.push(new Date(value.milestoneDate).getTime());
      ids.push(value.id);
      if (dates.length === data.milestones.length) {
        var id = ids[$.inArray(Math.min.apply(Math, dates), dates)]
        , res = $.grep(data.connections, function(task, key) {
          return task.pageSourceId === id
        })[0].pageTargetId;
        return res
      }
    })[0]; 
    document.write(filtered);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
&#13;
&#13;
&#13;