2017-05-11 23 views
0

動態平均計算我有一個JSON陣列等:經由lodash

[{ 
    "x": { 
     "x1": 1 
    }, 
    "y": { 
    "yt": 0, 
    "zt": 4, 
    "qa": 3, 
    "ft": 0, 
    ... 
    } 
}, 
{ 
    "x": { 
     "x1": 5 
    }, 
    "y": { 
    "yt": 10, 
    "zt": 2, 
    "qa": 0, 
    "ft": 0, 
    ... 
    } 
}] 

我想爲每個字段來計算平均值。結果結構應該相同。像:

{ 
     "x": { 
      "x1": 3 
     }, 
     "y": { 
     "yt": 5, 
     "zt": 3, 
     "qa": 1.5, 
     "ft": 0, 
     ... 
     } 
    } 

感謝

+0

_ 「有一個問題,如果數據爲0的代碼被太複雜了。」 _? – guest271314

+0

好吧,也許是我的代碼。沒關係那部分。我正在刪除它。 – serkan

回答

1

您可以合併使用傳播語法和lodash的_.mergeWith()的對象。 合併時,如果第二個參數(b)是一個數字,則將其除以原始數組中的項目數,以獲得它對總平均值的各自貢獻。如果第一個參數(a)是一個數字,只需加上它就可以不分割(避免多次分割),如果未定義則加0。

我已經添加了2個對象數組和3個對象數組的示例。

const getAvg = (data) => _.mergeWith({}, ...data, (a, b) => { 
 
    if(_.isNumber(b)) { 
 
    return ((b || 0)/data.length) + (_.isNumber(a) ? (a || 0) : 0); 
 
    } 
 
}); 
 

 
const data1 = [ 
 
{"x":{"x1":1},"y":{"yt":0,"zt":4,"qa":3,"ft":0}}, 
 
{"x":{"x1":5},"y":{"yt":10,"zt":2,"qa":0,"ft":0}} 
 
]; 
 

 
const data2 = [ 
 
{"x":{"x1":1},"y":{"yt":0,"zt":4,"qa":3,"ft":0}}, 
 
{"x":{"x1":5},"y":{"yt":10,"zt":2,"qa":0,"ft":0}}, 
 
{"x":{"x1":3},"y":{"yt":2,"zt":6,"qa":3,"ft":0}} 
 
]; 
 

 
const result1 = getAvg(data1); 
 

 
console.log('2 objects in the array: ', result1); 
 

 
const result2 = getAvg(data2); 
 

 
console.log('3 objects in the array: ', result2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

+0

這是一個很棒的方式!我使用data.map((arr)=> arr.ratings);過濾。因爲還有其他NaN領域。我是否也可以隱瞞上述功能? Lodash地圖不會返回與內建地圖功能相同的數據。 – serkan

+0

NaN函數是實際的'NaN'還是其他東西,比如對象,字符串等......?如果是這樣,他們會定期合併。如果他們的實際'NaN',將不得不處理它們,因爲'NaN'被認爲是javascript中的一個數字。無論如何,'_.mergeWith()'不會過濾屬性。 –

+0

這是一個文本。它可能也是一個實際的NaN。 – serkan

0

你可以先收集,並在相同的數據結構總結所有的值,然後用給定數組的長度calculkate由一個部門的平均值。

function getParts(array, result) { 
 
    function iter(o, r) { 
 
     Object.keys(o).forEach(function (k) { 
 
      if (o[k] && typeof o[k] === 'object') { 
 
       return iter(o[k], r[k] = r[k] || {}); 
 
      } 
 
      r[k] = (r[k] || 0) + o[k]; 
 
     }); 
 
    } 
 

 
    function avr(o) { 
 
     Object.keys(o).forEach(function (k) { 
 
      if (o[k] && typeof o[k] === 'object') { 
 
       return avr(o[k]); 
 
      } 
 
      o[k] = o[k] /data.length; 
 
     }); 
 
    } 
 

 
    data.forEach(function (a) { 
 
     iter(a, result); 
 
    }); 
 
    avr(result); 
 
} 
 

 
var data = [{ x: { x1: 1 }, y: { yt: 0, zt: 4, qa: 3, ft: 0, } }, { x: { x1: 5 }, y: { yt: 10, zt: 2, qa: 0, ft: 0, } }], 
 
    result = {}; 
 

 
getParts(data, result); 
 

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

0

let objectArray = [{ 
 
    "x": { 
 
     "x1": 1 
 
    }, 
 
    "y": { 
 
    "yt": 0, 
 
    "zt": 4, 
 
    "qa": 3, 
 
    "ft": 0, 
 
    } 
 
}, 
 
{ 
 
    "x": { 
 
     "x1": 5 
 
    }, 
 
    "y": { 
 
    "yt": 10, 
 
    "zt": 2, 
 
    "qa": 0, 
 
    "ft": 0, 
 
    } 
 
}]; 
 

 
function findAverage(array) { 
 
    
 
    let counter = {}, 
 
    result = {}, 
 
    i, 
 
    obj, 
 
    key, 
 
    subKey; 
 
    
 
    // Iterate through array 
 
    for (i = 0; i < array.length; i++) { 
 
    obj = array[i]; 
 
    // Copy each key in array element to counter object 
 
    for (key in obj) { 
 
     counter[key] = counter[key] || {}; 
 
     // Increment and keep count of key-values of counter based on values in array element 
 
     for (subKey in obj[key]) { 
 
     counter[key][subKey] = counter[key][subKey] || {total: 0, numElements: 0}; 
 
     counter[key][subKey].total += obj[key][subKey]; 
 
     counter[key][subKey].numElements += 1; 
 
     } 
 
    } 
 
    } 
 
    // Go back through counter to find average of all existing subkeys (based on incremented total and the number of elements recorded) and throw it into result object 
 
    for (key in counter) { 
 
    result[key] = result[key] || {}; 
 
    
 
    for (subKey in counter[key]) { 
 
     result[key][subKey] = counter[key][subKey].total/counter[key][subKey].numElements; 
 
    } 
 
    } 
 
    
 
    return result; 
 
} 
 

 
console.log(findAverage(objectArray));

設計不是絕對最佳,和複製對象可以遞歸不預先知道它們的結構來完成的,但我想保持的步驟儘可能清楚。

編輯爲允許測試爲片段。不知道你甚至可以這麼做!

0

var array = [{ 
 
    "x": { 
 
     "x1": 1 
 
    }, 
 
    "y": { 
 
    "yt": 0, 
 
    "zt": 4, 
 
    "qa": 3, 
 
    "ft": 0 
 
    } 
 
}, 
 
{ 
 
    "x": { 
 
     "x1": 5 
 
    }, 
 
    "y": { 
 
    "yt": 10, 
 
    "zt": 2, 
 
    "qa": 0, 
 
    "ft": 0 
 
    } 
 
}]; 
 
function aintob(){ 
 
    var o = {}; 
 
    var first = array[0], 
 
     second = array[1]; 
 
    var result = {x:{},y:{}}; 
 
    var each = function(letter, oa, ob){ 
 
    var i, 
 
    letter = {}; 
 
    for(i in oa){ 
 
     letter[i] = (oa[i]+ob[i])/2; 
 
    } 
 
    return letter; 
 
    } 
 
    o.x = each("x", first.x, second.x); 
 
    o.y = each("y", first.y, second.y); 
 
    return o; 
 
} 
 
console.log(aintob());