2016-09-23 132 views
1

我需要從Typescript中的對象數組構建自定義對象。遍歷對象數組並輸出自定義對象

在下面的給出示例中,如何計算Array中的salesman_1_name的次數,爲每個Salesman_1_name添加總額,並計算每個salesman_1_name的保修期是否爲空?所以,如果我有:

[ 
    {salesman_1_name:Brian, gross:100, warranty: Easycare}, 
    {salesman_1_name:Brian, gross:100, warranty: Easycare}, 
    {salesman_1_name:Brian, gross:100, warranty: null}, 
    {salesman_1_name:Kreso, gross:100, warranty: null}, 
    {salesman_1_name:Filip, gross:100, warranty: Easycare} 
] 

我需要輸出:

[ 
    Name:Brian, Count:3, Gross:300, WarrantyCount:2, 
    Name:Kreso, Count:1, Gross:100, WarrantyCount:0, 
    Name:Filip, Count:1, Gross:100, WarrantyCount:1 
] 
+0

是'Easycare'的一個字符串?你從哪裏得到'WarrantyCount'? –

+0

是的,我打算在示例中爲兩條「Brian」行添加保脩名稱。我需要計算,如果保修不爲空,並計數++ – BHead

+1

爲什麼你會得到'Filip ... WarrantyCount:1'和'Brian ... WarrantyCount:2'? –

回答

1

你可以使用一個對象作爲參照組的名稱,讓您的聚集。

var data = [{ salesman_1_name: 'Brian', gross: 100, warranty: 'Easycare' }, { salesman_1_name: 'Brian', gross: 100, warranty: 'Easycare' }, { salesman_1_name: 'Brian', gross: 100, warranty: null }, { salesman_1_name: 'Kreso', gross: 100, warranty: null }, { salesman_1_name: 'Filip', gross: 100, warranty: 'Easycare' }], 
 
    grouped = []; 
 

 
data.forEach(function (a) { 
 
    if (!this[a.salesman_1_name]) { 
 
     this[a.salesman_1_name] = { Name: a.salesman_1_name, Count: 0, Gross: 0, WarrantyCount: 0 }; 
 
     grouped.push(this[a.salesman_1_name]); 
 
    } 
 
    this[a.salesman_1_name].Count++; 
 
    this[a.salesman_1_name].Gross += a.gross; 
 
    a.warranty !== null && this[a.salesman_1_name].WarrantyCount++;  
 
}, Object.create(null)); 
 

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

+0

1/2:我大多喜歡你的方法,但這次我會挑剔。 「減少」應該是首選方法。有2個參數。該方法使用和額外的目標對象(爲什麼'Object.create(null)'而不是一個普通的對象字面值'{}')作爲一個映射或累加器對象,需要引用這個'this'(這就是用法/目的對於很多人來說,即使第二眼也不是很明顯)... –

+0

2/2:...另一方面,代碼仍然需要堅持一個'分組'外部對象作爲最終的累加器對象。通過'reduce'可以免費獲得所有的東西,回調的代碼變得更加優雅,並且更加可重用。 –

+0

如果我有像'toString'這樣的散列,那麼存在檢查會導致錯誤的結果。我使用forEach,因爲reduce的性質,在這個例子中總是相同的,對結果集的引用並沒有真正改變,像somthing作爲sum或單個基元/改變對象。 –

1
data.reduce((acc, cur) => { 
    const obj = acc.find(x => x.Name === cur.salesman_1_name); 
    if (obj) { 
    obj.Gross += cur.gross; 
    obj.WarrantyCount = cur.warranty !== null ? obj.WarrantyCount + 1 : obj.WarrantyCount; 
    } else { 
    acc.push({ Name: cur.salesman_1_name, Gross: cur.gross, WarrantyCount: cur.warranty !== null ? 1 : 0 }); 
    } 
    return acc; 
}, []); 
+0

「減少」每個迭代步驟真的不想要,也不需要搜索累積列表中的相關推銷員項目。 –

0

// Code goes here 
 

 
var data = [{ 
 
    salesman_1_name: 'Brian', 
 
    gross: 100, 
 
    warranty: 'Easycare' 
 
}, { 
 
    salesman_1_name: 'Brian', 
 
    gross: 100, 
 
    warranty: 'Easycare' 
 
}, { 
 
    salesman_1_name: 'Brian', 
 
    gross: 100, 
 
    warranty: null 
 
}, { 
 
    salesman_1_name: 'Kreso', 
 
    gross: 100, 
 
    warranty: null 
 
}, { 
 
    salesman_1_name: 'Filip', 
 
    gross: 100, 
 
    warranty: 'Easycare' 
 
}]; 
 

 

 
var result = (function(myArray) { 
 
    var obj = []; //also can be used Object.values(dataCollector) 
 
    var dataCollector = myArray.reduce(function(dataCollector, currentItem) { 
 

 
    if (!dataCollector[currentItem['salesman_1_name']]) { 
 
     dataCollector[currentItem['salesman_1_name']] = { 
 
     Name: currentItem.salesman_1_name, 
 
     Count: 0, 
 
     Gross: currentItem.gross, 
 
     WarrantyCount: currentItem['salesman_1_name'].warranty != null ? 0 : 1 
 
     }; 
 

 
    } else { 
 
     dataCollector[currentItem['salesman_1_name']].Count++; 
 
     dataCollector[currentItem['salesman_1_name']].Gross += currentItem.gross; 
 
     if (currentItem['salesman_1_name'].warranty !== null) { 
 
     dataCollector[currentItem['salesman_1_name']].WarrantyCount++; 
 
     } 
 

 
    } 
 

 
    return dataCollector; 
 

 
    }, {}); 
 

 
    for (var key in dataCollector) { 
 
    if (dataCollector.hasOwnProperty(key)) { 
 
     obj.push(dataCollector[key]); 
 
    } 
 
    } 
 
    return obj; 
 

 
})(data) 
 

 
console.log(result);

+0

@Vladulonut ... uhh ...兩個退出點 - 'return obj'和'return dataCollector' - 連同每個迭代'reduce'處理的提前退出的最終條件...'reduce '和它的累加器對象確實可以更優雅地使用......並且在最終條件下,不需要引用外部列表,因爲它被提供爲'reduce'回調函數的第4個參數,因此從而可以引用該回調中的縮小列表並處理尚未按名稱知道的數組。 –

+0

@PeterSeliger thx審查,我做了一些改變 –

0

var rawSalesmanData = [ 
 
    { salesman_1_name: "Brian", gross: 100, warranty: "Easycare" }, 
 
    { salesman_1_name: "Brian", gross: 100, warranty: "Easycare" }, 
 
    { salesman_1_name: "Brian", gross: 100, warranty: null }, 
 
    { salesman_1_name: "Kreso", gross: 100, warranty: null }, 
 
    { salesman_1_name: "Filip", gross: 100, warranty: "Easycare" } 
 
]; 
 

 
var salesmanSpecificList = rawSalesmanData.reduce(function (collector, rawDataItem/*, idx, rawDataList*/) { 
 

 
    var map  = collector.map; 
 
    var key  = rawDataItem.salesman_1_name; 
 
    var namedItem = map[key]; 
 

 
    if (!namedItem) { 
 
     namedItem = map[key] = { 
 
      name   : key, 
 
      occurencyCount : 0, 
 
      grossTotal  : 0, 
 
      warrantyCount : 0 
 
     }; 
 
     collector.list.push(namedItem); 
 
    } 
 
    namedItem.occurencyCount++; 
 
    namedItem.grossTotal = (namedItem.grossTotal + rawDataItem.gross); 
 
    namedItem.warrantyCount = (namedItem.warrantyCount + ((rawDataItem.warranty !== null) ? 1 : 0)); 
 

 
    return collector; 
 

 
}, { 
 

 
    map : {}, 
 
    list: [] 
 

 
}).list; 
 

 

 
console.log("salesmanSpecificList : ", salesmanSpecificList);