Chciałbym zsumować wartości przedmiotu.
Jestem przyzwyczajony do Pythona, gdzie byłoby po prostu:
sample = { 'a': 1 , 'b': 2 , 'c':3 };
summed = sum(sample.itervalues())
Poniższy kod działa, ale jest go dużo:
function obj_values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}
function list_sum( list ){
return list.reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});
}
function object_values_sum( obj ){
return list_sum(obj_values(obj));
}
var sample = { a: 1 , b: 2 , c:3 };
var summed = list_sum(obj_values(a));
var summed = object_values_sum(a)
Czy brakuje mi czegoś oczywistego, czy po prostu tak jest?
javascript
object
javascript-objects
Jonathan Vanasco
źródło
źródło
Object.keys().reduce
wygląda o wiele bardziej elegancko, jest o 60% wolniejszy.To może być takie proste:
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
Cytując MDN:
z
Object.values()
MDNz
Array.prototype.reduce()
MDNMożesz użyć tej funkcji w ten sposób:
sumValues({a: 4, b: 6, c: -5, d: 0}); // gives 5
Zauważ, że ten kod wykorzystuje niektóre funkcje ECMAScript, które nie są obsługiwane przez niektóre starsze przeglądarki (takie jak IE). Do skompilowania kodu może być konieczne użycie Babel .
źródło
Object.values()
, która zostanie polyfilled zfor
pętli na każdej przeglądarce oprócz Firefoksa. Nawet bez polyfillu jestfor
dla mnie 4x wolniejszy niż zwykła pętla.Object.values()
do tego czasu będą się implementować .reduce
wydaje się nieco bardziej niezawodna. Czy celowo pominąłeś analizę?Object.values()
jest obsługiwany przez wszystkie nowoczesne przeglądarki .Jeśli używasz lodash, możesz zrobić coś takiego
_.sum(_.values({ 'a': 1 , 'b': 2 , 'c':3 }))
źródło
Regularna
for
pętla jest dość zwięzła:var total = 0; for (var property in object) { total += object[property]; }
Może być konieczne dodanie,
object.hasOwnProperty
jeśli zmodyfikowałeś prototyp.źródło
Szczerze mówiąc, biorąc pod uwagę nasze „współczesne czasy”, w miarę możliwości wybrałbym podejście programowania funkcjonalnego, na przykład:
const sumValues = (obj) => Object.keys(obj).reduce((acc, value) => acc + obj[value], 0);
Nasz akumulator
acc
, zaczynając od wartości 0, gromadzi wszystkie zapętlone wartości naszego obiektu. Ma to dodatkową zaletę, że nie jest zależny od żadnych zmiennych wewnętrznych ani zewnętrznych; to stała funkcja, więc nie zostanie przypadkowo nadpisana ... wygraj w ES2015!źródło
Czy jest jakiś powód, dla którego nie używasz zwykłej
for...in
pętli?var sample = { a: 1 , b: 2 , c:3 }; var summed = 0; for (var key in sample) { summed += sample[key]; };
http://jsfiddle.net/vZhXs/
źródło
Teraz możesz skorzystać z
reduce
funkcji i otrzymać sumę.const object1 = { 'a': 1 , 'b': 2 , 'c':3 } console.log(Object.values(object1).reduce((a, b) => a + b, 0));
źródło
Jestem trochę spóźniony na imprezę, jednak jeśli potrzebujesz solidniejszego i bardziej elastycznego rozwiązania, oto mój wkład. Jeśli chcesz zsumować tylko określoną właściwość w zagnieżdżonej kombinacji obiekt / tablica, a także wykonać inne metody agregacji, oto mała funkcja, której używałem w projekcie React:
var aggregateProperty = function(obj, property, aggregate, shallow, depth) { //return aggregated value of a specific property within an object (or array of objects..) if ((typeof obj !== 'object' && typeof obj !== 'array') || !property) { return; } obj = JSON.parse(JSON.stringify(obj)); //an ugly way of copying the data object instead of pointing to its reference (so the original data remains unaffected) const validAggregates = [ 'sum', 'min', 'max', 'count' ]; aggregate = (validAggregates.indexOf(aggregate.toLowerCase()) !== -1 ? aggregate.toLowerCase() : 'sum'); //default to sum //default to false (if true, only searches (n) levels deep ignoring deeply nested data) if (shallow === true) { shallow = 2; } else if (isNaN(shallow) || shallow < 2) { shallow = false; } if (isNaN(depth)) { depth = 1; //how far down the rabbit hole have we travelled? } var value = ((aggregate == 'min' || aggregate == 'max') ? null : 0); for (var prop in obj) { if (!obj.hasOwnProperty(prop)) { continue; } var propValue = obj[prop]; var nested = (typeof propValue === 'object' || typeof propValue === 'array'); if (nested) { //the property is an object or an array if (prop == property && aggregate == 'count') { value++; } if (shallow === false || depth < shallow) { propValue = aggregateProperty(propValue, property, aggregate, shallow, depth+1); //recursively aggregate nested objects and arrays } else { continue; //skip this property } } //aggregate the properties value based on the selected aggregation method if ((prop == property || nested) && propValue) { switch(aggregate) { case 'sum': if (!isNaN(propValue)) { value += propValue; } break; case 'min': if ((propValue < value) || !value) { value = propValue; } break; case 'max': if ((propValue > value) || !value) { value = propValue; } break; case 'count': if (propValue) { if (nested) { value += propValue; } else { value++; } } break; } } } return value; }
Jest rekurencyjny, inny niż ES6 i powinien działać w większości pół-nowoczesnych przeglądarek. Używasz tego w ten sposób:
const onlineCount = aggregateProperty(this.props.contacts, 'online', 'count');
Podział parametrów:
obj = obiekt lub
właściwość tablicy = właściwość w zagnieżdżonych obiektach / tablicach, na których chcesz wykonać metodę
agregacji na agregate = metoda agregacji (suma, min, maksimum lub liczba)
płytka = może być ustawiona na true / false lub wartość liczbową
depth = należy pozostawić pustą lub niezdefiniowaną (służy do śledzenia kolejnych rekurencyjnych wywołań zwrotnych)
Shallow może służyć do zwiększenia wydajności, jeśli wiesz, że nie będziesz musiał przeszukiwać głęboko zagnieżdżonych danych. Na przykład, jeśli masz następującą tablicę:
[ { id: 1, otherData: { ... }, valueToBeTotaled: ? }, { id: 2, otherData: { ... }, valueToBeTotaled: ? }, { id: 3, otherData: { ... }, valueToBeTotaled: ? }, ... ]
Jeśli chcesz uniknąć zapętlania się przez właściwość otherData, ponieważ wartość, którą zamierzasz agregować, nie jest zagnieżdżona tak głęboko, możesz ustawić wartość shallow na true.
źródło
Użyj Lodash
import _ from 'Lodash'; var object_array = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]; return _.sumBy(object_array, 'c') // return => 9
źródło
let prices = { "apple": 100, "banana": 300, "orange": 250 }; let sum = 0; for (let price of Object.values(prices)) { sum += price; } alert(sum)
źródło
Natknąłem się na to rozwiązanie od @jbabey, próbując rozwiązać podobny problem. Po niewielkiej modyfikacji udało mi się to dobrze. W moim przypadku klucze obiektów to liczby (489) i łańcuchy („489”). Dlatego aby rozwiązać ten problem, każdy klucz jest analizowany. Poniższy kod działa:
var array = {"nR": 22, "nH": 7, "totB": "2761", "nSR": 16, "htRb": "91981"} var parskey = 0; for (var key in array) { parskey = parseInt(array[key]); sum += parskey; }; return(sum);
źródło
Ramda jedna wkładka:
import { compose, sum, values, } from 'ramda' export const sumValues = compose(sum, values);
Posługiwać się:
const summed = sumValues({ 'a': 1 , 'b': 2 , 'c':3 });
źródło
Możemy iteracyjne obiektu za pomocą w kluczowych i może wykonać dowolną operację arytmetyczną.
// input const sample = { 'a': 1, 'b': 2, 'c': 3 }; // var let sum = 0; // object iteration for (key in sample) { //sum sum += (+sample[key]); } // result console.log("sum:=>", sum);
źródło
Zsumuj wartość klucza obiektu przez analizę liczby całkowitej. Konwersja formatu string na liczbę całkowitą i sumowanie wartości
var obj = { pay: 22 }; obj.pay; console.log(obj.pay); var x = parseInt(obj.pay); console.log(x + 20);
źródło