2017-01-02 71 views
-1

我想在這裏實現的是一個結構化數據集,用於從名爲"timeTree"的數組中提取時間軸。訪問數組中新推入的對象的上下文

首先,我正在迭代有結束日期的目標。基於這個日期我想分類到正確的。正在使用

角進行渲染,我曾與渲染這種結構沒有問題,同樣不能說有關創建它...

我的問題是如何添加一個目標到一年,這是還沒有在陣列中?

scope.timeTree = []; 
_.each(goals, function(goal) { 
    if (goal.stateId != "FINISHED") { 

     var goalYear = new Date(goal.plannedEnd).getFullYear(); 
     var goalMonth = new Date(goal.plannedEnd).getMonth(); 

     if (scope.timeTree.length > 0) { 
     _.each(scope.timeTree, function(year) { 
      if (year.year === goalYear) { 
      _.each(year.months, function(month) { 
       if (month.month === goalMonth) { 
       month.goals.push(goal); 
       } else { 
       year.months.push({ 
        month: goalMonth, 
        goals: [] 
       }); 
       _.each(month.goals, function(goal) { 

       }) 
       } 
      }) 
      } else { 
      scope.timeTree.push({ 
       year: goalYear, 
       months: [] 
      }); 

      _.each(year.months, function(month) { 
       if (month.month === goalMonth) { 
       month.goals.push(goal); 
       } else { 

       } 
      }); 
      } 
     }) 
     } else { 
     // init structure 
     scope.timeTree.push({ 
      year: goalYear, 
      months: [] 
     }); 
     _.each(scope.timeTree, function(year) { 

      year.months.push({ 
      month: goalMonth, 
      goals: [] 
      }); 

      _.each(year.months, function(month) { 

      month.goals.push(goal); 


      }); 
     }); 
     } 
    } 
    } 
} 

在上面的代碼,特別是,當year.year不等於goalYear,我根本不知道該怎麼辦......我在今年的情況下(物體年份信息,以及那一年的月份,這些月份都有目標)但是我不希望在不同年度的情況下重複數月。我希望在我剛推動的一年中將目標推入月份領域。基本上,主要問題是if語句的負分支,當我必須將新對象推入數組中時,同時將目標推入剛剛創建(推送)的數組中。也許這不是一個好方法,所以我打開更好的解決方案。另一方面,如果你知道如何使這種確切的方法奏效,這將是很好的。

回答

0

我認爲深層嵌套和迭代可以很容易地編寫令人困惑的代碼。除非有充分的理由不使用香草JS,否則它應該足夠綽綽有餘。當然,在沒有深度嵌套的情況下編寫代碼應該是這裏的主要優先事項。

例子:

// In scope.timeTree, return me an array objects where it's year value matches goalYear 
var matching_year = scope.timeTree.filter(function(yearly_goal) { 
    return yearly_goal.year === goalYear; 
}); 

// If it does not exists, create one 
// Else, use that - there should only be 1 
if (matching_year.length === 0) { 
    var newTimeTree = {year: goalYear, months: []}; 
    matching_year = newTimeTree; 
    scope.timeTree.push(newTimeTree); 
} else { 
    matching_year = matching_year[0]; 
} 

// From the object with the matching year, find the object with the matching goalMonth 
var matching_month = matching_year.months.filter(function(monthly_goal) { 
    return monthly_goal.month === goalMonth; 
}); 

// If it does not exists, create one 
// Else, use that one 
if (matching_month.length === 0) { 
    var newGoal = {month: goalMonth, goals: []}; 
    matching_month = newGoal; 
    matching_year.months.push(newGoal); 
} else { 
    matching_month = matching_month[0]; 
} 

// Finally, pushed goal into the object that matches the year and the month 
matching_month.goals.push(goal); 

編輯:當然,如果你一定要,我注意到你正在使用underscore.js您_.each(列表,iteratee)。在這種情況下,你可以考慮用下面的定義here替代vanilla JS的過濾函數來實現下劃線JS的過濾功能。

0

您可以使用Map(ES6功能)快速查找您正在查找的年份和月份(在固定時間內)。然後使用Array.from到嵌套Map結構轉化爲最終的一個:

var scope = {}; // for snippet only 
 
// Sample data 
 
var goals = [ 
 
    { plannedEnd: '2015-12-01', text: 'Break', stateId: 'STARTED' }, 
 
    { plannedEnd: '2016-07-01', text: 'Break', stateId: 'STARTED' }, 
 
    { plannedEnd: '2016-01-01', text: 'Year', stateId: 'STARTED' }, 
 
    { plannedEnd: '2016-01-01', text: 'New', stateId: 'STARTED' }, 
 
    { plannedEnd: '2015-12-01', text: 'Christmas', stateId: 'STARTED' }, 
 
    { plannedEnd: '2016-07-01', text: 'Summer', stateId: 'STARTED' }, 
 
]; 
 

 
scope.timeTree = Array.from(
 
    goals.filter(goal => goal.stateId != "FINISHED") 
 
     .reduce((yearMap, goal) => { 
 
      var goalYear = new Date(goal.plannedEnd).getFullYear(); 
 
      var goalMonth = new Date(goal.plannedEnd).getMonth(); 
 
      // Store year in map. Create new entry if not yet there 
 
      if (!yearMap.has(goalYear)) yearMap.set(goalYear, new Map); 
 
      var monthMap = yearMap.get(goalYear); 
 
      // Same principle for month: 
 
      if (!monthMap.has(goalMonth)) monthMap.set(goalMonth, []); 
 
      monthMap.get(goalMonth).push(goal); 
 
      return yearMap; 
 
     }, new Map), // Start with empty Map 
 
    // Now convert to final structure, with second arg to main Array.from 
 
    ([year, monthMap]) => ({ 
 
     year, 
 
     months: Array.from(monthMap, ([month, goals]) => ({month, goals})) 
 
      // Optionally sort months 
 
      .sort((a,b) => a.month - b.month) 
 
    }) 
 
// Optionally sort the array by year 
 
).sort((a,b) => a.year - b.year); 
 

 
    
 
console.log(scope.timeTree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

0

感謝您的幫助。我需要的這個項目是在es5中構建的,所以使用新的javascript規範不是一種選擇,但是,不過謝謝,我肯定會在個人項目中使用它。 KnightNiwrem,我不得不爲了渲染目的而保留引用,所以不是過濾器,而是使用下劃線中的pick方法。這是最終的解決方案。

_.each(value, function(goal) { 
          if (goal.stateId != "FINISHED"){ 

           var goalYear = new Date(goal.plannedEnd).getFullYear(); 
           var goalMonth = new Date(goal.plannedEnd).getMonth(); 

           var matchingYear = _.find(scope.timeTree, function(year){ 
            return year.year === goalYear; 
           }) 

           if (!!matchingYear){ 
            var matchingMonth = _.find(matchingYear.months, function(month){ 
             return month.month === goalMonth; 
            }) 

            if (!!matchingMonth){ 
             matchingMonth.goals.push(goal); 
            } 
            else{ 
             matchingYear.months.push({ month: goalMonth, goals: [goal] }); 
            } 
           } 
           else{ 
            var newStructure = { year: goalYear, 
                 months: [{ month: goalMonth, goals: [goal] }] 
            } 

            scope.timeTree.push(newStructure); 
           } 
          } 
         })