Javascript reduce () on Object
есть хороший метод массива reduce() чтобы получить одно значение из массива. Пример:
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
каков наилучший способ достичь того же с объектами? Я хотел бы сделать это:
{
a: {value:1},
b: {value:2},
c: {value:3}
}.reduce(function(previous, current, index, array){
return previous.value + current.value;
});
однако, объект, кажется, не имеет никакого reduce() метод реализован.
10 ответов:
одним из вариантов будет
reducethekeys():var o = { a: {value:1}, b: {value:2}, c: {value:3} }; Object.keys(o).reduce(function (previous, key) { return previous + o[key].value; }, 0);при этом, вы хотите, чтобы указать начальное значение или 1-й раунд будет
'a' + 2.если вы хотите получить результат в виде объекта (
{ value: ... }), вам придется инициализировать и возвращать объект каждый раз:Object.keys(o).reduce(function (previous, key) { previous.value += o[key].value; return previous; }, { value: 0 });
во-первых, вы не совсем понимаете, что такое уменьшитьПредыдущее значение.
в вас псевдо код у вас есть
return previous.value + current.value, поэтомуpreviousзначение будет числом при следующем вызове, а не объектом.второе,
reduce- Это метод массива, а не объект, и вы не можете полагаться на порядок, когда вы повторяете свойства объекта (см.:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in, это применяется к
что вы на самом деле хотите в этом случае являются
Object.values. Вот краткий ES6 реализация с учетом этого:add = { a: {value:1}, b: {value:2}, c: {value:3} } total = Object.values(add).reduce((t, n) => t + n.value, 0) console.log(total) // 6или просто:
add = { a: 1, b: 2, c: 3 } total = Object.values(add).reduce((t, n) => t + n) console.log(total) // 6
Продлить Объекта.прототип.
Object.prototype.reduce = function( reduceCallback, initialValue ) { var obj = this, keys = Object.keys( obj ); return keys.reduce( function( prevVal, item, idx, arr ) { return reduceCallback( prevVal, item, obj[item], obj ); }, initialValue ); };пример использования.
var dataset = { key1 : 'value1', key2 : 'value2', key3 : 'value3' }; function reduceFn( prevVal, key, val, obj ) { return prevVal + key + ' : ' + val + '; '; } console.log( dataset.reduce( reduceFn, 'initialValue' ) ); 'Output' == 'initialValue; key1 : value1; key2 : value2; key3 : value3; '.Н радость, ребята!! ; -)
Это не очень сложно реализовать себя:
function reduceObj(obj, callback, initial) { "use strict"; var key, lastvalue, firstIteration = true; if (typeof callback !== 'function') { throw new TypeError(callback + 'is not a function'); } if (arguments.length > 2) { // initial value set firstIteration = false; lastvalue = initial; } for (key in obj) { if (!obj.hasOwnProperty(key)) continue; if (firstIteration) firstIteration = false; lastvalue = obj[key]; continue; } lastvalue = callback(lastvalue, obj[key], key, obj); } if (firstIteration) { throw new TypeError('Reduce of empty object with no initial value'); } return lastvalue; }действие:
var o = {a: {value:1}, b: {value:2}, c: {value:3}}; reduceObj(o, function(prev, curr) { prev.value += cur.value; return prev;}, {value:0}); reduceObj(o, function(prev, curr) { return {value: prev.value + curr.value};}); // both == { value: 6 }; reduceObj(o, function(prev, curr) { return prev + curr.value; }, 0); // == 6вы также можете добавить его в прототип объекта:
if (typeof Object.prototype.reduce !== 'function') { Object.prototype.reduce = function(callback, initial) { "use strict"; var args = Array.prototype.slice(arguments); args.unshift(this); return reduceObj.apply(null, args); } }
1:
[{value:5}, {value:10}].reduce((previousValue, currentValue) => { return {value: previousValue.value + currentValue.value}}) >> Object {value: 15}2:
[{value:5}, {value:10}].map(item => item.value).reduce((previousValue, currentValue) => {return previousValue + currentValue }) >> 153:
[{value:5}, {value:10}].reduce(function (previousValue, currentValue) { return {value: previousValue.value + currentValue.value}; }) >> Object {value: 15}
Если вы можете использовать массив, используйте массив, длина и порядок массива составляют половину его стоимости.
function reducer(obj, fun, temp){ if(typeof fun=== 'function'){ if(temp== undefined) temp= ''; for(var p in obj){ if(obj.hasOwnProperty(p)){ temp= fun(obj[p], temp, p, obj); } } } return temp; } var O={a:{value:1},b:{value:2},c:{value:3}} reducer(O, function(a, b){return a.value+b;},0);/* возвращаемое значение: (число) Шесть * /
вы можете использовать выражение генератора (поддерживается во всех браузерах в течение многих лет и в узле), чтобы получить пары ключ-значение в списке, который вы можете уменьшить:
>>> a = {"b": 3} Object { b=3} >>> [[i, a[i]] for (i in a) if (a.hasOwnProperty(i))] [["b", 3]]
поскольку это еще не было подтверждено в ответе, подчеркивание
reduceтакже работает для этого._.reduce({ a: {value:1}, b: {value:2}, c: {value:3} }, function(prev, current){ //prev is either first object or total value var total = prev.value || prev return total + current.value })Примечание
_.reduceвозвращает единственное значение (объект или иначе), если объект списка имеет только один элемент, без вызова функции итератора._.reduce({ a: {value:1} }, function(prev, current){ //not called }) //returns {value: 1} instead of 1
Comments