অবজেক্টগুলির একটি অ্যারে গ্রুপবাইয়ের সবচেয়ে কার্যকর পদ্ধতি


506

কোন অ্যারেতে গ্রুপপ্লে অবজেক্টগুলির সর্বাধিক দক্ষ উপায় কী?

উদাহরণস্বরূপ, অবজেক্টের এই অ্যারে দেওয়া:

[ 
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
]

আমি এই তথ্যটি একটি টেবিলে প্রদর্শন করছি। আমি বিভিন্ন পদ্ধতিতে গ্রুপবদ্ধ করতে চাই, তবে আমি মানগুলি যোগ করতে চাই।

আমি গ্রুপপ্লে ফাংশনের জন্য অ্যান্ডস্কোর.জেএস ব্যবহার করছি, এটি সহায়ক, তবে পুরো কৌশলটি করে না, কারণ আমি এগুলিকে এসকিউএল group byপদ্ধতির মতো "বিভক্ত" না করে "একীভূত" করতে চাই না ।

আমি যা খুঁজছি তা নির্দিষ্ট মানগুলি (যদি অনুরোধ করা হয়) করতে সক্ষম হয়।

সুতরাং আমি যদি গ্রুপপ্লে করতাম তবে আমি Phaseগ্রহণ করতে চাই:

[
    { Phase: "Phase 1", Value: 50 },
    { Phase: "Phase 2", Value: 130 }
]

এবং যদি আমি দলবদ্ধ Phase/ Stepকরতাম, আমি পেতাম :

[
    { Phase: "Phase 1", Step: "Step 1", Value: 15 },
    { Phase: "Phase 1", Step: "Step 2", Value: 35 },
    { Phase: "Phase 2", Step: "Step 1", Value: 55 },
    { Phase: "Phase 2", Step: "Step 2", Value: 75 }
]

এর জন্য কি কোনও সহায়ক স্ক্রিপ্ট রয়েছে, বা আমার কী বোঝা উচিত অ্যান্ডস্কোর.জেএস ব্যবহার করে, এবং তারপরে মোটটি নিজের মতো করে ফলাফলের অবজেক্টটি লুপ করে নেওয়া উচিত?

উত্তর:


755

আপনি যদি বাহ্যিক গ্রন্থাগারগুলি এড়াতে চান তবে আপনি সংক্ষেপে এর groupBy()মতো ভ্যানিলা সংস্করণটি প্রয়োগ করতে পারেন:

var groupBy = function(xs, key) {
  return xs.reduce(function(rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
  }, {});
};

console.log(groupBy(['one', 'two', 'three'], 'length'));

// => {3: ["one", "two"], 5: ["three"]}


18
আমি এইভাবে সংশোধন করব: s `x ​​xs.reduce (ফাংশন (আরভি, এক্স) {var ভি = কী উদাহরণস্বরূপ ফাংশন? কী (এক্স): এক্স [কী]; (আরভি [ভি] = আরভি [ভি] || [])। পুশ (এক্স); রিটার্ন আরভি;}, {});
back

109
এখানে অ্যারে আউটপুট দেয় এবং আপত্তিহীন নয়: groupByArray (xs, key) {রিটার্ন xs.reduce (ফাংশন (আরভি, এক্স) {চলুন v = কী উদাহরণস্বরূপ ফাংশন? কী (এক্স): এক্স [কী]; চলুন এল = আরভি .find ((r) => r&& r.key === v); if (el) {el.values.push (x);} অন্য {rv.push ({কী: ভি, মান: [x] });} রিটার্ন আরভি;}, []); }
tomitrescak

24
দুর্দান্ত, ঠিক আমার যা দরকার ছিল। অন্য কারও যদি এটির প্রয়োজন হয় তবে এখানে টাইপস্ক্রিপ্ট স্বাক্ষর রয়েছে:var groupBy = function<TItem>(xs: TItem[], key: string) : {[key: string]: TItem[]} { ...
মাইকেল স্যান্ডিনো

4
এটি মূল্যবান কিসের জন্য, টমিট্রেসাকের দ্রবণটি সুবিধাজনক হলেও কম কার্যকর, কারণ সন্ধান করুন () সম্ভবত ও (এন)। উত্তরের সমাধানটি হ'ল (এন), হ্রাস থেকে (বস্তুর অ্যাসাইনমেন্টটি হ'ল ও (1), যেমন ধাক্কা দেওয়া), তবে মন্তব্যটি ও (এন) * ও (এন) বা ও (এন ^ 2) বা এ কমপক্ষে ও (এনএলজিএন)
নর্থুর 157

21
যদি কেউ আগ্রহী হন তবে আমি এই ফাংশনটির আরও বেশি পঠনযোগ্য এবং টীকাযুক্ত সংস্করণ তৈরি করেছি এবং এটি একটি সংক্ষেপে রেখেছি : gist.github.com/robmathers/1830ce09695f759bf2c4df15c29dddd আমি এখানে কী ঘটছে তা বোঝার জন্য এটি সহায়ক বলে মনে করি।
ছিনতাইকারীরা

227

ES6 মানচিত্র অবজেক্ট ব্যবহার করা:

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
         const key = keyGetter(item);
         const collection = map.get(key);
         if (!collection) {
             map.set(key, [item]);
         } else {
             collection.push(item);
         }
    });
    return map;
}

// example usage

const pets = [
    {type:"Dog", name:"Spot"},
    {type:"Cat", name:"Tiger"},
    {type:"Dog", name:"Rover"}, 
    {type:"Cat", name:"Leo"}
];
    
const grouped = groupBy(pets, pet => pet.type);
    
console.log(grouped.get("Dog")); // -> [{type:"Dog", name:"Spot"}, {type:"Dog", name:"Rover"}]
console.log(grouped.get("Cat")); // -> [{type:"Cat", name:"Tiger"}, {type:"Cat", name:"Leo"}]
    
    

মানচিত্র সম্পর্কে: https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস / মানচিত্র


@ মর্টব, get()পদ্ধতিটি না বলে এটি কীভাবে পাবেন ? যা আমি চাই কীটি পাস না করেই আউটপুট প্রদর্শিত হয়
ফাই জাল ডং

@ ফাইজালডং: আমি নিশ্চিত না যে আপনার মামলার জন্য সবচেয়ে ভাল কি হবে? আমি যদি console.log(grouped.entries());জিসফিলের উদাহরণে লিখি তবে এটি একটি পুনরাবৃত্তিযোগ্য যা কী + মানগুলির অ্যারের মতো আচরণ করে returns আপনি এটি চেষ্টা করে দেখতে পারেন এবং এটি সাহায্য করে কিনা?
মার্টব

7
আপনিও চেষ্টা করতে পারেনconsole.log(Array.from(grouped));
17'কে

আমি এই উত্তরটি পছন্দ করি, খুব নমনীয়
বেনশাবত্নোয়াম

গ্রুপগুলিতে উপাদানগুলির সংখ্যা দেখতে:Array.from(groupBy(jsonObj, item => i.type)).map(i => ( {[i[0]]: i[1].length} ))
আহমেত Şimşek

105

ES6 সহ:

const groupBy = (items, key) => items.reduce(
  (result, item) => ({
    ...result,
    [item[key]]: [
      ...(result[item[key]] || []),
      item,
    ],
  }), 
  {},
);

3
অভ্যস্ত হতে কিছুটা সময় লাগে, তবে বেশিরভাগ সি ++ টেম্পলেটগুলিও করেন
লেভি হাস্কেল

2
আমি আমার ঘিলু wracked এবং এখনও বুঝতে বিশ্বের এটা থেকে শুরু কাজ করে ব্যর্থ ...result। এখন সে কারণে ঘুমাতে পারছি না।

7
মার্জিত, তবে বেদনাদায়কভাবে বৃহত্তর অ্যারেগুলিতে ধীরে ধীরে!
অসীম

4
লোল এটি কী
নিনো এককাপ্যাক

1
সহজ সমাধান। ধন্যবাদ
এজেকুইল টাভারেস

59

লিঙ্কের উত্তরটি আকর্ষণীয় হলেও এটি বেশ ভারী ওজনযুক্ত। আমার দৃষ্টিভঙ্গি কিছুটা আলাদা:

var DataGrouper = (function() {
    var has = function(obj, target) {
        return _.any(obj, function(value) {
            return _.isEqual(value, target);
        });
    };

    var keys = function(data, names) {
        return _.reduce(data, function(memo, item) {
            var key = _.pick(item, names);
            if (!has(memo, key)) {
                memo.push(key);
            }
            return memo;
        }, []);
    };

    var group = function(data, names) {
        var stems = keys(data, names);
        return _.map(stems, function(stem) {
            return {
                key: stem,
                vals:_.map(_.where(data, stem), function(item) {
                    return _.omit(item, names);
                })
            };
        });
    };

    group.register = function(name, converter) {
        return group[name] = function(data, names) {
            return _.map(group(data, names), converter);
        };
    };

    return group;
}());

DataGrouper.register("sum", function(item) {
    return _.extend({}, item.key, {Value: _.reduce(item.vals, function(memo, node) {
        return memo + Number(node.Value);
    }, 0)});
});

আপনি এটি জেএসবিনে কর্মে দেখতে পাচ্ছেন

আমি অ্যান্ডস্কোরে এমন কিছু দেখিনি যা যা করে তা hasকরে, যদিও আমার এটি অনুপস্থিত হতে পারে। এটি অনেকটা একই _.contains, তবে তুলনার _.isEqualচেয়ে বরং ব্যবহার করে ===। এগুলি ব্যতীত, বাকিগুলি সমস্যা-নির্দিষ্ট, যদিও জেনেরিক হওয়ার চেষ্টা সহ attempt

এখন DataGrouper.sum(data, ["Phase"])ফিরে

[
    {Phase: "Phase 1", Value: 50},
    {Phase: "Phase 2", Value: 130}
]

এবং DataGrouper.sum(data, ["Phase", "Step"])ফিরে

[
    {Phase: "Phase 1", Step: "Step 1", Value: 15},
    {Phase: "Phase 1", Step: "Step 2", Value: 35},
    {Phase: "Phase 2", Step: "Step 1", Value: 55},
    {Phase: "Phase 2", Step: "Step 2", Value: 75}
]

তবে sumএখানে কেবল একটি সম্ভাব্য ফাংশন। আপনি নিজের পছন্দ মতো অন্যকে নিবন্ধন করতে পারেন:

DataGrouper.register("max", function(item) {
    return _.extend({}, item.key, {Max: _.reduce(item.vals, function(memo, node) {
        return Math.max(memo, Number(node.Value));
    }, Number.NEGATIVE_INFINITY)});
});

এবং এখন DataGrouper.max(data, ["Phase", "Step"])ফিরে আসবে

[
    {Phase: "Phase 1", Step: "Step 1", Max: 10},
    {Phase: "Phase 1", Step: "Step 2", Max: 20},
    {Phase: "Phase 2", Step: "Step 1", Max: 30},
    {Phase: "Phase 2", Step: "Step 2", Max: 40}
]

অথবা আপনি এটি নিবন্ধিত হলে:

DataGrouper.register("tasks", function(item) {
    return _.extend({}, item.key, {Tasks: _.map(item.vals, function(item) {
      return item.Task + " (" + item.Value + ")";
    }).join(", ")});
});

তাহলে কলিং DataGrouper.tasks(data, ["Phase", "Step"])আপনাকে পেয়ে যাবে

[
    {Phase: "Phase 1", Step: "Step 1", Tasks: "Task 1 (5), Task 2 (10)"},
    {Phase: "Phase 1", Step: "Step 2", Tasks: "Task 1 (15), Task 2 (20)"},
    {Phase: "Phase 2", Step: "Step 1", Tasks: "Task 1 (25), Task 2 (30)"},
    {Phase: "Phase 2", Step: "Step 2", Tasks: "Task 1 (35), Task 2 (40)"}
]

DataGrouperনিজেই একটি ফাংশন। আপনি এটিকে আপনার ডেটা এবং যে গোষ্ঠীগুলির দ্বারা গ্রুপ করতে চান তার একটি তালিকা দিয়ে কল করতে পারেন। এটি এমন একটি অ্যারে প্রদান করে যার উপাদানগুলি দুটি বৈশিষ্ট্য সহ বস্তুযুক্ত: keyগ্রুপযুক্ত বৈশিষ্ট্যগুলির সংগ্রহ, valsকীতে নেই এমন অবশিষ্ট বৈশিষ্ট্যযুক্ত বস্তুর একটি অ্যারে। উদাহরণস্বরূপ, প্রদান DataGrouper(data, ["Phase", "Step"])করবে:

[
    {
        "key": {Phase: "Phase 1", Step: "Step 1"},
        "vals": [
            {Task: "Task 1", Value: "5"},
            {Task: "Task 2", Value: "10"}
        ]
    },
    {
        "key": {Phase: "Phase 1", Step: "Step 2"},
        "vals": [
            {Task: "Task 1", Value: "15"}, 
            {Task: "Task 2", Value: "20"}
        ]
    },
    {
        "key": {Phase: "Phase 2", Step: "Step 1"},
        "vals": [
            {Task: "Task 1", Value: "25"},
            {Task: "Task 2", Value: "30"}
        ]
    },
    {
        "key": {Phase: "Phase 2", Step: "Step 2"},
        "vals": [
            {Task: "Task 1", Value: "35"}, 
            {Task: "Task 2", Value: "40"}
        ]
    }
]

DataGrouper.registerএকটি ফাংশন গ্রহণ করে এবং একটি নতুন ফাংশন তৈরি করে যা প্রাথমিক ডেটা এবং বৈশিষ্ট্যগুলিকে গ্রুপ অনুসারে গ্রহণ করে। এই নতুন ফাংশনটি উপরের হিসাবে আউটপুট ফর্ম্যাটটি নেয় এবং পরিবর্তে তাদের প্রত্যেকের বিরুদ্ধে আপনার ফাংশনটি চালায়, নতুন অ্যারে ফিরিয়ে দেয়। উত্পন্ন ফাংশনটি DataGrouperআপনার সরবরাহ করা নাম অনুসারে সম্পত্তি হিসাবে সংরক্ষণ করা হয় এবং আপনি কেবল স্থানীয় রেফারেন্স চাইলে ফিরে আসে।

ঠিক আছে যে অনেক ব্যাখ্যা। কোডটি যুক্তিসঙ্গতভাবে সোজা, আমি আশা করি!


হাই .. আপনি কেবল একটি মান অনুসারে গ্রুপ এবং সমষ্টি দেখতে পাচ্ছেন, তবে আমি যদি মান 1 এবং ভ্যালু 2 এবং মান 3 দিয়ে যোগফল চাই ... আপনার সমাধান আছে কি?
সামুয়েল অস্পিনা

@ সামুয়েলসপিনা আপনি কি কখনও এটি করার উপায় খুঁজে পেয়েছেন?
কিভাবেমুচিচিআইস টুমুচচিজ

50

আমি লড্যাশ গোষ্ঠীটি যাচাই করে দেখব যে আপনি যা খুঁজছেন ঠিক তেমনই করছেন। এটি বেশ লাইটওয়েট এবং সত্যই সহজ।

ঝাঁকুনির উদাহরণ: https://jsfiddle.net/r7szvt5k/

আপনার অ্যারের নামটি arrলোড্যাশের সাথে গোষ্ঠী অনুসারে প্রদান করা হয়:

import groupBy from 'lodash/groupBy';
// if you still use require:
// const groupBy = require('lodash/groupBy');

const a = groupBy(arr, function(n) {
  return n.Phase;
});
// a is your array grouped by Phase attribute

1
এই উত্তরটি কি সমস্যাযুক্ত নয়? এমন একাধিক উপায় রয়েছে যাতে লোডাস _.groupBy ফলাফল ওপি অনুরোধ করছে ফলাফলের ফর্ম্যাটে নেই। (1) ফলাফলটি একটি অ্যারে নয়। (২) লোডাশ অবজেক্ট (গুলি) ফলাফলের "মান" হয়ে উঠেছে "কী"।
এমজি 1075

44

এটি সম্ভবত আরও সহজেই সম্পন্ন হয়েছে linq.jsযা জাভাস্ক্রিপ্টে লিমকুইয়ের সত্যিকারের বাস্তবায়ন ( ডেমো ) হিসাবে লক্ষ্য করা যায়:

var linq = Enumerable.From(data);
var result =
    linq.GroupBy(function(x){ return x.Phase; })
        .Select(function(x){
          return {
            Phase: x.Key(),
            Value: x.Sum(function(y){ return y.Value|0; })
          };
        }).ToArray();

ফলাফল:

[
    { Phase: "Phase 1", Value: 50 },
    { Phase: "Phase 2", Value: 130 }
]

বা আরও সহজভাবে স্ট্রিং-ভিত্তিক নির্বাচক ( ডেমো ) ব্যবহার করে:

linq.GroupBy("$.Phase", "",
    "k,e => { Phase:k, Value:e.Sum('$.Value|0') }").ToArray();

আমরা এখানে গ্রুপিংয়ের সময় একাধিক সম্পত্তি ব্যবহার করতে পারি:GroupBy(function(x){ return x.Phase; })
অমিত

36

আপনি এ Mapথেকে একটি ES6 তৈরি করতে পারেন array.reduce()

const groupedMap = initialArray.reduce(
    (entryMap, e) => entryMap.set(e.id, [...entryMap.get(e.id)||[], e]),
    new Map()
);

অন্যান্য সমাধানগুলির তুলনায় এর কয়েকটি সুবিধা রয়েছে:

  • এটির জন্য কোনও লাইব্রেরির প্রয়োজন নেই (যেমন: _.groupBy() )
  • আপনি Mapকোনও বস্তুর পরিবর্তে একটি জাভাস্ক্রিপ্ট পান (যেমন ফেরত দিয়েছিলেন _.groupBy())। এর প্রচুর সুবিধা রয়েছে , সহ:
    • এটি প্রথমে আইটেম যুক্ত করার ক্রমটি মনে করে,
    • কীগুলি কেবল স্ট্রিংয়ের পরিবর্তে যে কোনও ধরণের হতে পারে।
  • Mapআরও কার্যকর ফলাফল যা অ্যারেগুলির একটি অ্যারে। তবে আপনি যদি অ্যারেগুলির একটি অ্যারে চান তবে আপনি Array.from(groupedMap.entries())( [key, group array]জোড়ার অ্যারের জন্য ) বা Array.from(groupedMap.values())(অ্যারের সাধারণ অ্যারের জন্য ) কল করতে পারেন ।
  • এটি বেশ নমনীয়; প্রায়শই, আপনি এই মানচিত্রটির সাথে পরবর্তী যা যা করার পরিকল্পনা করেছিলেন তা হ্রাসের অংশ হিসাবে সরাসরি করা যেতে পারে।

শেষ পয়েন্টের উদাহরণ হিসাবে, কল্পনা করুন যে আমার কাছে আইডির মাধ্যমে একটি (অগভীর) মার্জ করতে চাই এমন একটি সামগ্রীর অ্যারে রয়েছে:

const objsToMerge = [{id: 1, name: "Steve"}, {id: 2, name: "Alice"}, {id: 1, age: 20}];
// The following variable should be created automatically
const mergedArray = [{id: 1, name: "Steve", age: 20}, {id: 2, name: "Alice"}]

এটি করার জন্য, আমি সাধারণত আইডি দ্বারা গোষ্ঠীকরণ এবং তারপরে ফলাফল প্রাপ্ত অ্যারেগুলির প্রতিটি মার্জ করে শুরু করব। পরিবর্তে, আপনি সরাসরি একত্রিত করতে পারেন reduce():

const mergedArray = Array.from(
    objsToMerge.reduce(
        (entryMap, e) => entryMap.set(e.id, {...entryMap.get(e.id)||{}, ...e}),
        new Map()
    ).values()
);

1
কেন জানি এর বেশি ভোট নেই? এটি সংক্ষিপ্ত, পাঠযোগ্য (আমার কাছে) এবং দক্ষ দেখায়এটিa.reduce(function(em, e){em.set(e.id, (em.get(e.id)||[]).concat([e]));return em;}, new Map())
IE11 এ


18

আপনি এটি আলাসকল জাভাস্ক্রিপ্ট লাইব্রেরি সহ করতে পারেন :

var data = [ { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
             { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }];

var res = alasql('SELECT Phase, Step, SUM(CAST([Value] AS INT)) AS [Value] \
                  FROM ? GROUP BY Phase, Step',[data]);

JsFizz এ এই উদাহরণ চেষ্টা করুন ।

বিটিডাব্লু: বড় অ্যারেগুলিতে (100000 রেকর্ড এবং আরও অনেক) আলাস্কল দ্রুত থম লিনক। JsPref এ পরীক্ষা দেখুন

মন্তব্যসমূহ:

  • এখানে আমি মান বর্গাকার বন্ধনীগুলিতে রেখেছি কারণ VALUE এসকিউএল-তে একটি কীওয়ার্ড
  • স্ট্রিংয়ের মানগুলিকে সংখ্যার ধরণে রূপান্তর করতে আমার CAST () ফাংশনটি ব্যবহার করতে হবে।

18
Array.prototype.groupBy = function(keyFunction) {
    var groups = {};
    this.forEach(function(el) {
        var key = keyFunction(el);
        if (key in groups == false) {
            groups[key] = [];
        }
        groups[key].push(el);
    });
    return Object.keys(groups).map(function(key) {
        return {
            key: key,
            values: groups[key]
        };
    });
};

15

এমডিএন তাদের নথিতে এই উদাহরণ রয়েছে exampleArray.reduce()

// Grouping objects by a property
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Grouping_objects_by_a_property#Grouping_objects_by_a_property

var people = [
  { name: 'Alice', age: 21 },
  { name: 'Max', age: 20 },
  { name: 'Jane', age: 20 }
];

function groupBy(objectArray, property) {
  return objectArray.reduce(function (acc, obj) {
    var key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  }, {});
}

var groupedPeople = groupBy(people, 'age');
// groupedPeople is:
// { 
//   20: [
//     { name: 'Max', age: 20 }, 
//     { name: 'Jane', age: 20 }
//   ], 
//   21: [{ name: 'Alice', age: 21 }] 
// }

14

যদিও প্রশ্নের কিছু উত্তর রয়েছে এবং উত্তরগুলি কিছুটা জটিল দেখায়, আমি নেস্টেড (প্রয়োজনে) সাথে গ্রুপ-বাই জন্য ভ্যানিলা জাভাস্ক্রিপ্ট ব্যবহার করার পরামর্শ দিই Map

function groupBy(array, groups, valueKey) {
    var map = new Map;
    groups = [].concat(groups);
    return array.reduce((r, o) => {
        groups.reduce((m, k, i, { length }) => {
            var child;
            if (m.has(o[k])) return m.get(o[k]);
            if (i + 1 === length) {
                child = Object
                    .assign(...groups.map(k => ({ [k]: o[k] })), { [valueKey]: 0 });
                r.push(child);
            } else {
                child = new Map;
            }
            m.set(o[k], child);
            return child;
        }, map)[valueKey] += +o[valueKey];
        return r;
    }, [])
};

var data = [{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" }, { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }];

console.log(groupBy(data, 'Phase', 'Value'));
console.log(groupBy(data, ['Phase', 'Step'], 'Value'));
.as-console-wrapper { max-height: 100% !important; top: 0; }


9

মিউটেশন ব্যতীত:

const groupBy = (xs, key) => xs.reduce((acc, x) => Object.assign({}, acc, {
  [x[key]]: (acc[x[key]] || []).concat(x)
}), {})

console.log(groupBy(['one', 'two', 'three'], 'length'));
// => {3: ["one", "two"], 5: ["three"]}

8

এই সমাধানটি কোনও স্বেচ্ছাসেবী ফাংশন নেয় (কী নয়) তাই এটি উপরের সমাধানগুলির চেয়ে আরও নমনীয় এবং তীর ফাংশনগুলিকে মঞ্জুরি দেয় যা লিনকিউতে ব্যবহৃত ল্যাম্বডা এক্সপ্রেশনগুলির অনুরূপ :

Array.prototype.groupBy = function (funcProp) {
    return this.reduce(function (acc, val) {
        (acc[funcProp(val)] = acc[funcProp(val)] || []).push(val);
        return acc;
    }, {});
};

দ্রষ্টব্য: আপনি প্রসারিত করতে চান কিনা Array প্রোটোটাইপটি নির্ভর করে।

বেশিরভাগ ব্রাউজারে সমর্থিত উদাহরণ:

[{a:1,b:"b"},{a:1,c:"c"},{a:2,d:"d"}].groupBy(function(c){return c.a;})

তীর ফাংশন (ES6) ব্যবহার করে উদাহরণ:

[{a:1,b:"b"},{a:1,c:"c"},{a:2,d:"d"}].groupBy(c=>c.a)

প্রত্যাবর্তনের উপরে উভয় উদাহরণ:

{
  "1": [{"a": 1, "b": "b"}, {"a": 1, "c": "c"}],
  "2": [{"a": 2, "d": "d"}]
}

আমি ES6 সমাধানটি অনেক পছন্দ করেছি। অ্যারে প্রোটোটাইপটি বাড়িয়ে না দিয়ে কেবল একটি সামান্য let key = 'myKey'; let newGroupedArray = myArrayOfObjects.reduce(function (acc, val) { (acc[val[key]] = acc[val[key]] || []).push(val); return acc;});
বিভাজন

8

আমি আমার পদ্ধতির পরামর্শ দিতে চাই প্রথমে পৃথক গোষ্ঠীকরণ এবং একত্রিত করা। প্রোটোটাইপিকাল "গ্রুপ বাই" ফাংশন ঘোষণা করতে দিন। প্রতিটি অ্যারে উপাদানকে গোষ্ঠীভুক্ত করার জন্য এটি "হ্যাশ" স্ট্রিং তৈরি করতে অন্য ফাংশন লাগে।

Array.prototype.groupBy = function(hash){
  var _hash = hash ? hash : function(o){return o;};

  var _map = {};
  var put = function(map, key, value){
    if (!map[_hash(key)]) {
        map[_hash(key)] = {};
        map[_hash(key)].group = [];
        map[_hash(key)].key = key;

    }
    map[_hash(key)].group.push(value); 
  }

  this.map(function(obj){
    put(_map, obj, obj);
  });

  return Object.keys(_map).map(function(key){
    return {key: _map[key].key, group: _map[key].group};
  });
}

যখন গোষ্ঠীকরণ করা হয়ে থাকে আপনি আপনার ক্ষেত্রে কীভাবে প্রয়োজন ডেটা একত্রিত করতে পারেন

data.groupBy(function(o){return JSON.stringify({a: o.Phase, b: o.Step});})
    /* aggreagating */
    .map(function(el){ 
         var sum = el.group.reduce(
           function(l,c){
             return l + parseInt(c.Value);
           },
           0
         );
         el.key.Value = sum; 
         return el.key;
    });

সাধারণভাবে এটি কাজ করে। আমি ক্রোম কনসোলে এই কোডটি পরীক্ষা করেছি। এবং ভুলগুলি উন্নত করতে এবং এটি নির্দ্বিধায় নির্দ্বিধায়;)


ধন্যবাদ! পদ্ধতির প্রতি ভালবাসা করুন এবং আমার প্রয়োজনগুলি পুরোপুরি ফিট করুন (আমার একত্রিত করার প্রয়োজন নেই)।
আবেরাউদ

আমি মনে করি আপনি নিজের লাইনটি পুট (): map[_hash(key)].key = key;তে পরিবর্তন করতে চান map[_hash(key)].key = _hash(key);
স্কটি ডটনেট

6

কল্পনা করুন যে আপনার কাছে এরকম কিছু রয়েছে:

[{id:1, cat:'sedan'},{id:2, cat:'sport'},{id:3, cat:'sport'},{id:4, cat:'sedan'}]

এই করে: const categories = [...new Set(cars.map((car) => car.cat))]

আপনি এটি পাবেন: ['sedan','sport']

ব্যাখ্যা: ১. প্রথমত, আমরা একটি অ্যারে পাস করে একটি নতুন সেট তৈরি করছি। যেহেতু সেট কেবল অনন্য মানকেই মঞ্জুরি দেয়, সমস্ত অনুলিপি সরানো হবে।

  1. এখন সদৃশগুলি চলে গেছে, আমরা স্প্রেড অপারেটরটি ব্যবহার করে এটিকে আবার অ্যারেতে রূপান্তর করতে যাচ্ছি ...

দস্তাবেজ সেট করুন: https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস / সেট স্প্রেড অপারেটর ডক : https://developer.mozilla.org/en-US/docs/Web/JavaScript / রেফারেন্স / অপারেটর / Spread_syntax


আমি আপনার উত্তরটি খুব পছন্দ করি, এটি সবচেয়ে সংক্ষিপ্ত একটি, তবে আমি এখনও যুক্তিটি বুঝতে পারি না, বিশেষত, এখানে দলবদ্ধকরণ কার? এটি স্প্রেড অপারেটর (...)? বা 'নতুন সেট ()'? দয়া করে আমাদের এটি ব্যাখ্যা করুন ... আপনাকে ধন্যবাদ
ইভান

1
1. প্রথমে, আমরা একটি অ্যারে পাস করে একটি নতুন সেট তৈরি করছি। যেহেতু সেট কেবল অনন্য মানকেই মঞ্জুরি দেয়, সমস্ত অনুলিপি সরানো হবে। ২. এখন নকলগুলি চলে গেছে, আমরা স্প্রেড অপারেটরটি ব্যবহার করে এটিকে আবার অ্যারেতে রূপান্তর করতে যাচ্ছি ... ডক সেট করুন: developer.mozilla.org/en-US/docs/Web/JavaScript/References/… স্প্রেড অপারেটর: ডেভেলপার.মোজিলা.আর.ইন-
ইউএস / ডকস / ওয়েবে / জাভা স্ক্রিপ্ট / রেফারেন্স /

ঠিক আছে, পেয়েছেন ... ব্যাখ্যার জন্য আপনাকে ধন্যবাদ স্যার :)
ইভান

আপনাকে স্বাগতম!
ইয়াগো গেহেরস

6

উত্তর চেক করা হয়েছে - কেবল অগভীর গোষ্ঠীকরণ। এটি হ্রাস বুঝতে খুব সুন্দর। প্রশ্ন অতিরিক্ত সামগ্রিক গণনার সমস্যাও সরবরাহ করে।

কিছু ক্ষেত্র (গুলি) দ্বারা 1 টি গণনা করা কী নাম এবং 2) পছন্দসই কীগুলির তালিকা সরবরাহ করে এবং এর অনন্য মানগুলিকে এসকিউএল গ্রুপের মতো রুট কীগুলিতে রূপান্তর করে গোষ্ঠীকরণের সম্পূর্ণ সমাধানের জন্য এখানে রিয়েল গ্রুপের মাধ্যমে কিছু ক্ষেত্র (গুলি) দ্বারা অবজেক্টের অ্যারে জন্য সম্পূর্ণ সমাধান দেওয়া হয়েছে is বাই করে।

const inputArray = [ 
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];

var outObject = inputArray.reduce(function(a, e) {
  // GROUP BY estimated key (estKey), well, may be a just plain key
  // a -- Accumulator result object
  // e -- sequentally checked Element, the Element that is tested just at this itaration

  // new grouping name may be calculated, but must be based on real value of real field
  let estKey = (e['Phase']); 

  (a[estKey] ? a[estKey] : (a[estKey] = null || [])).push(e);
  return a;
}, {});

console.log(outObject);

সাথে খেলুন estKey- আপনি একের পর এক ক্ষেত্রের দ্বারা দলবদ্ধ করতে পারেন, অতিরিক্ত সমষ্টি, গণনা বা অন্যান্য প্রক্রিয়াজাতকরণ যুক্ত করতে পারেন।

এছাড়াও আপনি পুনরাবৃত্তভাবে ডেটা গ্রুপ করতে পারেন। উদাহরণস্বরূপ প্রথমদিকে দলবদ্ধ করুন Phase, তারপরে Stepক্ষেত্র এবং এই জাতীয় কিছু। অতিরিক্তভাবে ফ্যাট বিশ্রামের ডেটা বন্ধ করে দিন।

const inputArray = [
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
{ Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
{ Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
{ Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
{ Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
  ];

/**
 * Small helper to get SHALLOW copy of obj WITHOUT prop
 */
const rmProp = (obj, prop) => ( (({[prop]:_, ...rest})=>rest)(obj) )

/**
 * Group Array by key. Root keys of a resulting array is value
 * of specified key.
 *
 * @param      {Array}   src     The source array
 * @param      {String}  key     The by key to group by
 * @return     {Object}          Object with groupped objects as values
 */
const grpBy = (src, key) => src.reduce((a, e) => (
  (a[e[key]] = a[e[key]] || []).push(rmProp(e, key)),  a
), {});

/**
 * Collapse array of object if it consists of only object with single value.
 * Replace it by the rest value.
 */
const blowObj = obj => Array.isArray(obj) && obj.length === 1 && Object.values(obj[0]).length === 1 ? Object.values(obj[0])[0] : obj;

/**
 * Recoursive groupping with list of keys. `keyList` may be an array
 * of key names or comma separated list of key names whom UNIQUE values will
 * becomes the keys of the resulting object.
 */
const grpByReal = function (src, keyList) {
  const [key, ...rest] = Array.isArray(keyList) ? keyList : String(keyList).trim().split(/\s*,\s*/);
  const res = key ? grpBy(src, key) : [...src];
  if (rest.length) {
for (const k in res) {
  res[k] = grpByReal(res[k], rest)
}
  } else {
for (const k in res) {
  res[k] = blowObj(res[k])
}
  }
  return res;
}

console.log( JSON.stringify( grpByReal(inputArray, 'Phase, Step, Task'), null, 2 ) );


5
groupByArray(xs, key) {
    return xs.reduce(function (rv, x) {
        let v = key instanceof Function ? key(x) : x[key];
        let el = rv.find((r) => r && r.key === v);
        if (el) {
            el.values.push(x);
        }
        else {
            rv.push({
                key: v,
                values: [x]
            });
        }
        return rv;
    }, []);
}

এই এক আউটপুট অ্যারে।


4

পূর্ববর্তী উত্তরের উপর ভিত্তি করে

const groupBy = (prop) => (xs) =>
  xs.reduce((rv, x) =>
    Object.assign(rv, {[x[prop]]: [...(rv[x[prop]] || []), x]}), {});

এবং যদি আপনার পরিবেশ সমর্থন করে তবে অবজেক্ট স্প্রেড সিনট্যাক্সের সাথে নজর দেওয়া একটু সুন্দর।

const groupBy = (prop) => (xs) =>
  xs.reduce((acc, x) => ({
    ...acc,
    [ x[ prop ] ]: [...( acc[ x[ prop ] ] || []), x],
  }), {});

এখানে, আমাদের রিডিউসার আংশিকভাবে গঠিত রিটার্ন মান গ্রহণ করে (একটি শূন্য বস্তু দিয়ে শুরু করে) এবং পূর্ববর্তী রিটার্ন মানের স্প্রেড আউট সদস্যদের সমন্বিত একটি বস্তু প্রদান করে, যার সাথে একটি নতুন সদস্য যার বর্তমানের পুনরুত্থানের মান থেকে গণনা করা হয় propএবং যার মান সেই মানের বর্তমান মান সহ সেই মানচিত্রের সমস্ত মানের একটি তালিকা।


3

Array.prototype.groupBy = function (groupingKeyFn) {
    if (typeof groupingKeyFn !== 'function') {
        throw new Error("groupBy take a function as only parameter");
    }
    return this.reduce((result, item) => {
        let key = groupingKeyFn(item);
        if (!result[key])
            result[key] = [];
        result[key].push(item);
        return result;
    }, {});
}

var a = [
	{type: "video", name: "a"},
  {type: "image", name: "b"},
  {type: "video", name: "c"},
  {type: "blog", name: "d"},
  {type: "video", name: "e"},
]
console.log(a.groupBy((item) => item.type));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


3

ES6 ব্যবহার করে সমাধানটি পড়ার পক্ষে এখানে একটি বাজে, কঠিন's

export default (arr, key) => 
  arr.reduce(
    (r, v, _, __, k = v[key]) => ((r[k] || (r[k] = [])).push(v), r),
    {}
  );

এটি এমনকি কীভাবে কাজ করে জিজ্ঞাসা করার জন্য, এখানে একটি ব্যাখ্যা এখানে রয়েছে:

  • দু'জনেই =>আপনার ফ্রি আছেreturn

  • Array.prototype.reduceফাংশন 4 পরামিতি পর্যন্ত সময় নেয়। সেই কারণেই পঞ্চম প্যারামিটার যুক্ত করা হচ্ছে যাতে আমরা একটি ডিফল্ট মান ব্যবহার করে প্যারামিটার ঘোষণা স্তরে গ্রুপ (কে) এর জন্য একটি সস্তা ভেরিয়েবল ঘোষণা করতে পারি। (হ্যাঁ, এটি যাদু)

  • যদি আমাদের বর্তমান গ্রুপটি পূর্ববর্তী পুনরাবৃত্তির উপর বিদ্যমান না থাকে তবে আমরা একটি নতুন খালি অ্যারে তৈরি করি ((r[k] || (r[k] = []))এটি বাম দিকের ভাবের মূল্যায়ন করবে, অন্য কথায় একটি বিদ্যমান অ্যারে বা খালি অ্যারে , এই কারণেই এই pushঅভিব্যক্তির পরপরই আছে , কারণ যে কোনও উপায়ে আপনি একটি অ্যারে পাবেন।

  • যখন একটি থাকে return, কমা ,অপারেটর এই দৃশ্যের জন্য টিক্কৃত পূর্ববর্তী গোষ্ঠীটিকে ফিরিয়ে দিয়ে বামতম মানটি বাতিল করবে।

একই কাজ করে এমন সংস্করণটি বোঝার জন্য এটি হ'ল:

export default (array, key) => 
  array.reduce((previous, currentItem) => {
    const group = currentItem[key];
    if (!previous[group]) previous[group] = [];
    previous[group].push(currentItem);
    return previous;
  }, {});

2
আপনি কি
এইটিকে

@ নুয়ানডাম্মিকা - উভয় => আপনার কাছে একটি ফ্রি "রিটার্ন" রয়েছে - হ্রাস কার্যটি 4 পরামিতি অবধি নেয়। এজন্য পঞ্চম প্যারামিটার যুক্ত করা হচ্ছে যাতে আমরা গ্রুপ (কে) এর জন্য সস্তা ভেরিয়েবল ঘোষণা করতে পারি। - পূর্ববর্তী মানটি যদি আমাদের বর্তমান গোষ্ঠীটি না করে থাকে তবে আমরা একটি নতুন খালি গোষ্ঠী তৈরি করি ((আরআর [কে] || (আর [কে] = [])) এটি বাম দিকের অভিব্যক্তিতে মূল্যায়ন করবে, অন্যথায় একটি অ্যারে বা একটি খালি অ্যারে, এই কেন যে এক্সপ্রেশনের পরে একটি তাৎক্ষণিক ধাক্কা হয় -। সেখানে একটি ফিরতি যখন, কমা অপারেটর বামদিকের মান বাতিল করবে, tweaked, পূর্ববর্তী গ্রুপ ফিরিয়ে আনে।
darkndream

2

জেনেরিক Array.prototype.groupBy()সরঞ্জাম তৈরি করতে দেয় । কেবল বিভিন্নতার জন্য আসুন কিছু পুনরাবৃত্তির পদ্ধতির সাথে মিলে কিছু হাস্কেললেস্কো প্যাটার্নের জন্য স্প্রেড অপারেটরটি ES6 ফ্যানসিটি ব্যবহার করুন। এছাড়াও আসুন আমরা Array.prototype.groupBy()একটি কলব্যাক গ্রহণ করতে পারি যা আইটেমটি ( e) সূচি ( i) এবং প্রয়োগ করা অ্যারে ( a) আর্গুমেন্ট হিসাবে গ্রহণ করে।

Array.prototype.groupBy = function(cb){
                            return function iterate([x,...xs], i = 0, r = [[],[]]){
                                     cb(x,i,[x,...xs]) ? (r[0].push(x), r)
                                                       : (r[1].push(x), r);
                                     return xs.length ? iterate(xs, ++i, r) : r;
                                   }(this);
                          };

var arr = [0,1,2,3,4,5,6,7,8,9],
    res = arr.groupBy(e => e < 5);
console.log(res);


2

সিজারের উত্তরটি ভাল, তবে কেবল অ্যারের অভ্যন্তরের উপাদানগুলির অভ্যন্তরীণ বৈশিষ্ট্যগুলির জন্য (স্ট্রিংয়ের ক্ষেত্রে দৈর্ঘ্য) কাজ করে।

এই বাস্তবায়ন আরও কাজ করে: এই লিঙ্ক

const groupBy = function (arr, f) {
    return arr.reduce((out, val) => {
        let by = typeof f === 'function' ? '' + f(val) : val[f];
        (out[by] = out[by] || []).push(val);
        return out;
    }, {});
};

আশাকরি এটা সাহায্য করবে...


2

@ মর্টব থেকে, @ জমার্সেলি উত্তর এবং এই পোস্ট থেকে ,

আমি সীমিত মানেরJSON.stringify() জন্য পরিচয় হওয়ার সুযোগটি নিই গ্রুপের একাধিক কলামের ।

তৃতীয় পক্ষ ছাড়া

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
        const key = keyGetter(item);
        if (!map.has(key)) {
            map.set(key, [item]);
        } else {
            map.get(key).push(item);
        }
    });
    return map;
}

const pets = [
    {type:"Dog", age: 3, name:"Spot"},
    {type:"Cat", age: 3, name:"Tiger"},
    {type:"Dog", age: 4, name:"Rover"}, 
    {type:"Cat", age: 3, name:"Leo"}
];

const grouped = groupBy(pets,
pet => JSON.stringify({ type: pet.type, age: pet.age }));

console.log(grouped);

তৃতীয় পক্ষের সাথে লোদাশ

const pets = [
    {type:"Dog", age: 3, name:"Spot"},
    {type:"Cat", age: 3, name:"Tiger"},
    {type:"Dog", age: 4, name:"Rover"}, 
    {type:"Cat", age: 3, name:"Leo"}
];

let rslt = _.groupBy(pets, pet => JSON.stringify(
 { type: pet.type, age: pet.age }));

console.log(rslt);

কীগেটর অপরিবর্তিত ফেরত দেয়
আসবার আলি

@ অস্বরআলি আমি আমার স্নিপেটটি Chrome এর কনসোল - সংস্করণ 66.0.3359.139 (অফিসিয়াল বিল্ড) (-৪-বিট) দিয়ে পরীক্ষা করেছি। এবং সবকিছু ঠিক আছে। আপনি কি দয়া করে ডিবাগিং ব্রেক পয়েন্টটি রাখতে পারেন এবং কীগিটারটি সংজ্ঞায়িত হয়েছে তা দেখুন। এটি সম্ভবত ব্রাউজার সংস্করণের কারণে।
প্রণিথন টি।

2

reduceফাংশনের জন্য সমর্থন সহ ES6 ভিত্তিক সংস্করণ সংস্করণ iteratee

iterateeফাংশনটি সরবরাহ না করা হলে প্রত্যাশার মতোই কাজ করে :

const data = [{id: 1, score: 2},{id: 1, score: 3},{id: 2, score: 2},{id: 2, score: 4}]

const group = (arr, k) => arr.reduce((r, c) => (r[c[k]] = [...r[c[k]] || [], c], r), {});

const groupBy = (arr, k, fn = () => true) => 
  arr.reduce((r, c) => (fn(c[k]) ? r[c[k]] = [...r[c[k]] || [], c] : null, r), {});

console.log(group(data, 'id'))     // grouping via `reduce`
console.log(groupBy(data, 'id'))   // same result if `fn` is omitted
console.log(groupBy(data, 'score', x => x > 2 )) // group with the iteratee

ওপি প্রশ্নের প্রসঙ্গে:

const data = [ { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" }, { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" }, { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" }, { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" }, { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" } ]

const groupBy = (arr, k) => arr.reduce((r, c) => (r[c[k]] = [...r[c[k]] || [], c], r), {});
const groupWith = (arr, k, fn = () => true) => 
  arr.reduce((r, c) => (fn(c[k]) ? r[c[k]] = [...r[c[k]] || [], c] : null, r), {});

console.log(groupBy(data, 'Phase'))
console.log(groupWith(data, 'Value', x => x > 30 ))  // group by `Value` > 30

আর একটি ES6 সংস্করণ যা গোষ্ঠীকরণকে বিপরীত করে এবং valuesহিসাবে keysএবং হিসাবে ব্যবহার keysকরে grouped values:

const data = [{A: "1"}, {B: "10"}, {C: "10"}]

const groupKeys = arr => 
  arr.reduce((r,c) => (Object.keys(c).map(x => r[c[x]] = [...r[c[x]] || [], x]),r),{});

console.log(groupKeys(data))

দ্রষ্টব্য: ফাংশনগুলি সংক্ষিপ্ততার জন্য এবং কেবল ধারণাটি সম্পর্কিত জন্য তাদের সংক্ষিপ্ত আকারে (একটি লাইন) পোস্ট করা হয়েছে। আপনি এগুলি প্রসারিত করতে এবং অতিরিক্ত ত্রুটি পরীক্ষা করা ইত্যাদি যোগ করতে পারেন


2

আমি ঘোষিত-জেএসগুলি যাচাই করে দেখব যা groupByমনে হচ্ছে আপনি যা করছেন ঠিক তা করে। ইহা ও:

  • খুব পারফরম্যান্ট (পারফরম্যান্স বেঞ্চমার্ক )
  • টাইপস্ক্রিপ্টে লিখিত তাই সমস্ত টাইপিংস অন্তর্ভুক্ত করা হয়।
  • এটি তৃতীয় পক্ষের অ্যারের মতো অবজেক্টগুলি ব্যবহার করার জন্য কার্যকর করা হচ্ছে না।
import { Reducers } from 'declarative-js';
import groupBy = Reducers.groupBy;
import Map = Reducers.Map;

const data = [
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 1", Value: "5" },
    { Phase: "Phase 1", Step: "Step 1", Task: "Task 2", Value: "10" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 1", Value: "15" },
    { Phase: "Phase 1", Step: "Step 2", Task: "Task 2", Value: "20" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 1", Value: "25" },
    { Phase: "Phase 2", Step: "Step 1", Task: "Task 2", Value: "30" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 1", Value: "35" },
    { Phase: "Phase 2", Step: "Step 2", Task: "Task 2", Value: "40" }
];

data.reduce(groupBy(element=> element.Step), Map());
data.reduce(groupBy('Step'), Map());

1
let groupbyKeys = function(arr, ...keys) {
  let keysFieldName = keys.join();
  return arr.map(ele => {
    let keysField = {};
    keysField[keysFieldName] = keys.reduce((keyValue, key) => {
      return keyValue + ele[key]
    }, "");
    return Object.assign({}, ele, keysField);
  }).reduce((groups, ele) => {
    (groups[ele[keysFieldName]] = groups[ele[keysFieldName]] || [])
      .push([ele].map(e => {
        if (keys.length > 1) {
          delete e[keysFieldName];
        }
        return e;
    })[0]);
    return groups;
  }, {});
};

console.log(groupbyKeys(array, 'Phase'));
console.log(groupbyKeys(array, 'Phase', 'Step'));
console.log(groupbyKeys(array, 'Phase', 'Step', 'Task'));

1

এখানে একটি ES6 সংস্করণ রয়েছে যা নাল সদস্যদের উপর ভাঙবে না

function groupBy (arr, key) {
  return (arr || []).reduce((acc, x = {}) => ({
    ...acc,
    [x[key]]: [...acc[x[key]] || [], x]
  }), {})
}

1

শুধু স্কট স্যয়েটের উত্তর যুক্ত করতে , কিছু লোক মন্তব্যগুলিতে জিজ্ঞাসা করছিলেন যে কীভাবে তার ফাংশনটি কেবলমাত্র একটি মানকে গোষ্ঠীভুক্ত না করে গোষ্ঠী মান 1, মান 2 ইত্যাদিতে ব্যবহার করতে হয়।

যা লাগে তা হ'ল তার যোগফলটি সম্পাদনা করা:

DataGrouper.register("sum", function(item) {
    return _.extend({}, item.key,
        {VALUE1: _.reduce(item.vals, function(memo, node) {
        return memo + Number(node.VALUE1);}, 0)},
        {VALUE2: _.reduce(item.vals, function(memo, node) {
        return memo + Number(node.VALUE2);}, 0)}
    );
});

মূলটি (ডেটাগ্রুপ) অপরিবর্তিত রেখে:

var DataGrouper = (function() {
    var has = function(obj, target) {
        return _.any(obj, function(value) {
            return _.isEqual(value, target);
        });
    };

    var keys = function(data, names) {
        return _.reduce(data, function(memo, item) {
            var key = _.pick(item, names);
            if (!has(memo, key)) {
                memo.push(key);
            }
            return memo;
        }, []);
    };

    var group = function(data, names) {
        var stems = keys(data, names);
        return _.map(stems, function(stem) {
            return {
                key: stem,
                vals:_.map(_.where(data, stem), function(item) {
                    return _.omit(item, names);
                })
            };
        });
    };

    group.register = function(name, converter) {
        return group[name] = function(data, names) {
            return _.map(group(data, names), converter);
        };
    };

    return group;
}());

1

সঙ্গে সাজানোর বৈশিষ্ট্য

export const groupBy = function groupByArray(xs, key, sortKey) {
      return xs.reduce(function(rv, x) {
        let v = key instanceof Function ? key(x) : x[key];
        let el = rv.find(r => r && r.key === v);

        if (el) {
          el.values.push(x);
          el.values.sort(function(a, b) {
            return a[sortKey].toLowerCase().localeCompare(b[sortKey].toLowerCase());
          });
        } else {
          rv.push({ key: v, values: [x] });
        }

        return rv;
      }, []);
    };

নমুনা:

var state = [
    {
      name: "Arkansas",
      population: "2.978M",
      flag:
  "https://upload.wikimedia.org/wikipedia/commons/9/9d/Flag_of_Arkansas.svg",
      category: "city"
    },{
      name: "Crkansas",
      population: "2.978M",
      flag:
        "https://upload.wikimedia.org/wikipedia/commons/9/9d/Flag_of_Arkansas.svg",
      category: "city"
    },
    {
      name: "Balifornia",
      population: "39.14M",
      flag:
        "https://upload.wikimedia.org/wikipedia/commons/0/01/Flag_of_California.svg",
      category: "city"
    },
    {
      name: "Florida",
      population: "20.27M",
      flag:
        "https://upload.wikimedia.org/wikipedia/commons/f/f7/Flag_of_Florida.svg",
      category: "airport"
    },
    {
      name: "Texas",
      population: "27.47M",
      flag:
        "https://upload.wikimedia.org/wikipedia/commons/f/f7/Flag_of_Texas.svg",
      category: "landmark"
    }
  ];
console.log(JSON.stringify(groupBy(state,'category','name')));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.