জাভাস্ক্রিপ্ট অবজেক্ট উপর () হ্রাস


180

অ্যারে 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()পদ্ধতি প্রয়োগ করা হয়েছে বলে মনে হয় না ।


1
আপনি ব্যবহার করছেন Underscore.js?
সেটেন

নাঃ। অ্যান্ডস্কোর বস্তুর জন্য হ্রাস সরবরাহ করে?
পাভেল এস

মনে নেই। আমি জানি এটির একটি reduceপদ্ধতি আছে। আমি সেখানে চেক করব। যদিও, সমাধানটি তেমন কঠিন বলে মনে হচ্ছে না।
সেটেন

1
@ শেথেন মালেনো, @ পাভেল: হ্যাঁ _অবজেক্টের জন্য হ্রাস আছে। নিশ্চিত না যে এটি দুর্ঘটনাক্রমে কাজ করেছে বা যদি অবজেক্ট সমর্থন ইচ্ছাকৃত হয়েছিল তবে আপনি এই প্রশ্নের উদাহরণ হিসাবে কোনও বস্তুটি পাস করতে পারবেন এবং এটি (ধারণাগতভাবে) for..inপ্রতিটি চাবির মধ্যে পাওয়া মানগুলির সাথে আপনার পুনরাবৃত্তিকে ফাংশন বলবে ।
রোয়াতিন মার্থ

উত্তর:


53

আপনি এই ক্ষেত্রে আসলে যা চান তা হ'ল Object.values। এটি মাথায় রেখে এখানে একটি সংক্ষিপ্ত ES6 বাস্তবায়ন রয়েছে:

const add = {
  a: {value:1},
  b: {value:2},
  c: {value:3}
}

const total = Object.values(add).reduce((t, {value}) => t + value, 0)

console.log(total) // 6

বা সহজভাবে:

const add = {
  a: 1,
  b: 2,
  c: 3
}

const total = Object.values(add).reduce((t, n) => t + n)

console.log(total) // 6

এটি অ্যারে.প্রোটোটাইপ.ভ্যালু () যা আপনি লিঙ্ক করেছেন - এখনই সম্পাদিত
জোনাথন উড

281

একটি বিকল্প হবে :reducekeys()

var o = { 
    a: {value:1}, 
    b: {value:2}, 
    c: {value:3} 
};

Object.keys(o).reduce(function (previous, key) {
    return previous + o[key].value;
}, 0);

এটির সাহায্যে আপনি একটি প্রাথমিক মান নির্দিষ্ট করতে চান বা প্রথম রাউন্ডটি হবে 'a' + 2

আপনি যদি কোনও অবজেক্ট ( { value: ... }) হিসাবে ফলাফলটি চান , আপনাকে প্রতিটি বারের জন্য আরম্ভ করতে হবে এবং ফেরত দিতে হবে:

Object.keys(o).reduce(function (previous, key) {
    previous.value += o[key].value;
    return previous;
}, { value: 0 });

14
উত্তম উত্তর তবে এটি অবজেক্ট.কিগুলির পরিবর্তে অবজেক্ট.ওয়ালিউস ব্যবহার করা বেশি পঠনযোগ্য কারণ আমরা কীগুলি নয় এখানে মানগুলি নিয়ে উদ্বিগ্ন। এটি এর মতো হওয়া উচিত: অবজেক্ট.ভ্যালু (ও) .ড্রেস ((মোট, বর্তমান) => মোট + কারেন্ট.ভালিউ, 0);
মিনা লুক

3
অবজেক্ট.ভ্যালুজের কাছে অবজেক্ট.কিগুলি থেকে অনেক খারাপ ব্রাউজার সমর্থন রয়েছে, তবে আপনি যদি কোনও পলিফিল ব্যবহার করেন বা আপনি বাবেলের সাথে প্রতিস্থাপন করেন তবে এটি কোনও সমস্যা হতে পারে না
duhaime

ঠিক, আমি এটি চাবিগুলিতে ব্যবহার করছিলাম যা মঙ্গো মডেল থেকে বীট অর্জন করেছে, এবং আমি কীগুলি হ্রাস করার ফলে প্রাথমিক মূল্য হিসাবে একটি খালি বস্তুটি দিয়েছি, এবং আমি যতটা @babel/plugin-proposal-object-rest-spreadপ্লাগইন ব্যবহার করছি , আমি এতে সঞ্চয়ের মানটি ছড়িয়েছিলাম রিটার্ন হ্রাস এবং এটি একটি কবজির মতো কাজ করে, তবে আমি যদি কিছু ভুল করে থাকি তবে আমি হতাশ হয়েছি কারণ কারণ আমি হ্রাসের প্রাথমিক মানকে মান্য করতে পেরেছিলাম এবং আপনার উত্তর আমাকে প্রমাণ করেছে যে আমি সঠিক কাজটি করেছি!
a_m_dev

55

ES6 বাস্তবায়ন: অবজেক্ট.এন্ট্রি ()

const o = {
  a: {value: 1},
  b: {value: 2},
  c: {value: 3}
};

const total = Object.entries(o).reduce(function (total, pair) {
  const [key, value] = pair;
  return total + value;
}, 0);

3
Object.entries(o); // returns [['value',1],['value',2],['value',3]]
faboulaws

1
কনস্ট [কী, মান] = জোড়; আমি এই দেখা যায় না!
মার্টিন মিজার

9
@ মার্টিন-মিজার - এটিকে বলা হয় ডেস্ট্রাকচারিং। এমনকি আমরা এই লাইনটি বাদ function (total, pair)দিতে পারিfunction (total, [key, value])
Jakub Zawiślak

entriesএটি করার একটি পরিষ্কার উপায় যদিও keysএটি কম পারফরম্যান্ট। hackernoon.com/…
রোবডন

@ ফাবাউলজ অবজেক্ট.এন্ট্রি (ও); // রিটার্ন [["a", {মান: 1}], ["বি", {মান: 2}], ["সি", {মান: 3}]]
টমাস

19

প্রথমত, এর আগের মানটি হ্রাস করার বিষয়টি আপনি পুরোপুরি পাবেন না ।

আপনার সিউডো কোডে আপনার রয়েছে return previous.value + current.value, সুতরাং previousমানটি পরের কলের একটি নম্বর হবে, কোনও বস্তু নয়।

দ্বিতীয়ত, reduceএকটি অ্যারে পদ্ধতি, কোনও অবজেক্টের নয়, এবং আপনি যখন কোনও বস্তুর বৈশিষ্ট্যগুলি পুনরাবৃত্তি করছেন তখন আপনি আদেশের উপর নির্ভর করতে পারবেন না (দেখুন: https://developer.mozilla.org/en-US/docs/ জাভাস্ক্রিপ্ট / রেফারেন্স / বিবৃতি / এর জন্য ... এতে , অবজেক্ট.কিগুলিতেও প্রয়োগ করা হয়); সুতরাং আমি নিশ্চিত না যে reduceকোনও বস্তুর উপর প্রয়োগ করা অর্থবোধ করে কিনা ।

তবে, যদি অর্ডারটি গুরুত্বপূর্ণ না হয় তবে আপনি তা পেতে পারেন:

Object.keys(obj).reduce(function(sum, key) {
    return sum + obj[key].value;
}, 0);

অথবা আপনি কেবলমাত্র বস্তুর মানটি ম্যাপ করতে পারেন :

Object.keys(obj).map(function(key) { return this[key].value }, obj).reduce(function (previous, current) {
    return previous + current;
});

ES6 তে পিএস ফ্যাট অ্যার ফাংশনটির সিনট্যাক্স সহ (ইতিমধ্যে ফায়ারফক্স নাইটে রয়েছে), আপনি কিছুটা সঙ্কুচিত করতে পারেন:

Object.keys(obj).map(key => obj[key].value).reduce((previous, current) => previous + current);

3

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 })

>> 15

3:

[{value:5}, {value:10}].reduce(function (previousValue, currentValue) {
      return {value: previousValue.value + currentValue.value};
})

>> Object {value: 15}

2

অবজেক্ট.প্রোটোটাইপ প্রসারিত করুন।

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; '.

এন'জয়! ;-)


-1, এখন ভবিষ্যতের সমস্ত অবজেক্টগুলিতে আপনার একটি নতুন অগণিত
জোহান


1
দয়া করে এর মতো বেস প্রোটোটাইপটি পরিবর্তন করবেন না। ভবিষ্যতের বিকাশকারীদের একই কোড বেসে কাজ করার ফলে এটি অনেক সমস্যার সৃষ্টি করতে পারে
adam.k

হ্যাঁ, এটি একটি "বানরের প্যাচিং" এই সমাধানটি 6 বছর আগে লেখা হয়েছিল এবং এখন খুব প্রাসঙ্গিক নয়, কেবল মনে রাখবেন এবং উদাহরণস্বরূপ, Object.entries()2021
1247458

2

আপনি হ্রাস করতে পারেন এমন একটি তালিকার মূল-মান জোড়া পেতে আপনি একটি জেনারেটর এক্সপ্রেশন (এখন বছরের জন্য সমস্ত ব্রাউজারে সমর্থিত, এবং নোডে) ব্যবহার করতে পারেন:

>>> a = {"b": 3}
Object { b=3}

>>> [[i, a[i]] for (i in a) if (a.hasOwnProperty(i))]
[["b", 3]]

2

একটি অবজেক্টকে অ্যারেতে পরিণত করা যেতে পারে: অবজেক্ট.এন্ট্রি () , অবজেক্ট.কিজ () , অবজেক্ট.ভালিউস () এবং তারপরে অ্যারে হিসাবে হ্রাস করা যেতে পারে। তবে আপনি মধ্যবর্তী অ্যারে তৈরি না করে কোনও বস্তুও হ্রাস করতে পারবেন।

আমি বস্তুগুলির সাথে কাজ করার জন্য একটি সামান্য সহায়ক লাইব্রেরি অজেক্ট তৈরি করেছি ।

npm install --save odict

এটা আছে reduceফাংশন যা খুব ভালো কাজ করে Array.prototype.reduce () :

export const reduce = (dict, reducer, accumulator) => {
  for (const key in dict)
    accumulator = reducer(accumulator, dict[key], key, dict);
  return accumulator;
};

আপনি এটিকে নির্ধারণ করতে পারেন:

Object.reduce = reduce;

এই পদ্ধতি হিসাবে খুব দরকারী!

সুতরাং আপনার প্রশ্নের উত্তরটি হ'ল:

const result = Object.reduce(
  {
    a: {value:1},
    b: {value:2},
    c: {value:3},
  },
  (accumulator, current) => (accumulator.value += current.value, accumulator), // reducer function must return accumulator
  {value: 0} // initial accumulator value
);

1

আপনি যদি একটি অ্যারে ব্যবহার করতে পারেন তবে একটি অ্যারে ব্যবহার করবেন না, একটি অ্যারের দৈর্ঘ্য এবং ক্রম এর অর্ধেক মূল্যবান।

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);

/ * প্রত্যাবর্তিত মূল্য: (সংখ্যা) 6 * /


1

নিজেকে বাস্তবায়ন করা খুব কঠিন নয়:

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);
    }
}

0

যেহেতু এটি এখনও একটি উত্তরে সত্যই নিশ্চিত হওয়া যায় নি, তাই অ্যান্ডস্কোর এর 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

"এই অন্যান্য লাইব্রেরিটি ব্যবহার করে দেখুন" দরকারী নয়
গ্রুনিয়ন শাফটো

আপনার পক্ষে দরকারী নয়
ক্রিস ডলফিন

0

এই এক লাইনারের তীর ফাংশনটি ব্যবহার করে দেখুন

Object.values(o).map(a => a.value, o).reduce((ac, key, index, arr) => ac+=key)

0

আর একবার চেষ্টা কর. এটি অন্যান্য ভেরিয়েবল থেকে সংখ্যা বাছাই করবে।

const obj = {
   a: 1,
   b: 2,
   c: 3
};
const result = Object.keys(obj)
.reduce((acc, rec) => typeof obj[rec] === "number" ? acc.concat([obj[rec]]) : acc, [])
.reduce((acc, rec) => acc + rec)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.