ऑब्जेक्ट की एक सरणी पर समूहीकरण करने के लिए सबसे कुशल विधि


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
मैं इस तरह से संशोधित करूंगा: `` वापसी xs.reduce (फ़ंक्शन (आरवी, एक्स) {var v = कुंजी इंस्टोफ़ फ़ंक्शन। कुंजी (x): x [कुंजी]? (rv [v] = rv [v] || [])। धक्का (एक्स); वापसी आरवी;}, {}); `` `कॉलबैक फ़ंक्शंस को एक सॉर्टिंग मानदंड वापस करने की अनुमति देता है
y_nk

109
यहाँ एक है जो अरैज़ आउटपुट करता है और ऑब्जेक्ट नहीं: groupByArray (xs, key) {रिटर्न xs.reduce (फ़ंक्शन (rv, x) {let v = key instof फंक्शन? की (x): x [key]? El = rv .find (r) => r && r.key === v); यदि (el) {el.values.push (x);} और {{rv.push ({कुंजी: v, मान]: [x] });} वापसी rv;}, []); }
tomitrescak

24
महान, बस मुझे क्या चाहिए। यदि किसी को इसकी आवश्यकता है, तो यहां टाइपस्क्रिप्ट हस्ताक्षर हैं:var groupBy = function<TItem>(xs: TItem[], key: string) : {[key: string]: TItem[]} { ...
माइकल सैंडिनो

4
क्या यह लायक है के लिए, tomitrescak के समाधान, जबकि सुविधाजनक है, काफी कम कुशल है, जैसा कि पाते हैं () शायद O (n) है। उत्तर में हल O (n) है, कम से (ऑब्जेक्ट असाइनमेंट O (1) है, जैसा कि धक्का है), जबकि टिप्पणी O (n) * O (n) या O (n ^ 2) या पर है कम से कम O (nlgn)
narthur157

21
अगर किसी को दिलचस्पी है, तो मैंने इस फ़ंक्शन का एक अधिक पठनीय और एनोटेट संस्करण बनाया और इसे एक जिस्ट में डाल दिया: gist.github.com/robmathers/1830ce09695f759bf2c4df15bdddddd मैंने इसे समझने के लिए मददगार पाया कि वास्तव में यहाँ क्या हो रहा है।
डकैत

228

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/JavaScript/Reference/Global_Objects/Map


@mortb, get()विधि को कॉल किए बिना इसे कैसे प्राप्त करें ? जो मैं चाहता हूं कि आउटपुट बिना कुंजी को पास किए प्रदर्शित हो
Fai Zal Dong

@ फ़ाइजलडोंग: मुझे यकीन नहीं है कि आपके मामले के लिए सबसे अच्छा क्या होगा? अगर मैं console.log(grouped.entries());jsfiddle उदाहरण में लिखता हूं तो यह एक पुनरावृत्ति देता है जो कुंजियों + मूल्यों की एक सरणी की तरह व्यवहार करता है। क्या आप कोशिश कर सकते हैं और देखें कि क्या यह मदद करता है?
मोर्टब

7
आप भी कोशिश कर सकते हैंconsole.log(Array.from(grouped));
मोर्टब

मुझे यह जवाब बहुत पसंद है, बहुत ही लचीला
benshabatnoam

समूहों में तत्वों की संख्या को देखने के लिए:Array.from(groupBy(jsonObj, item => i.type)).map(i => ( {[i[0]]: i[1].length} ))
Ahmet ekimşek

105

ES6 के साथ:

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

3
इसकी आदत
लेवी हास्केल

2
मैंने अपने दिमाग को मिटा दिया और फिर भी यह समझने में नाकाम रहा कि दुनिया में यह किस तरह से शुरू होता है ...result। अब मैं उस वजह से सो नहीं सकता।

7
सुरुचिपूर्ण, लेकिन बड़े सरणियों पर दर्दनाक रूप से धीमा!
infinity1975

4
lol यह क्या है
Nino whatkopac

1
आसान समाधान। धन्यवाद
एज़ेकिएल Tavares

59

हालांकि linq का जवाब दिलचस्प है, लेकिन यह काफी भारी है। मेरा दृष्टिकोण कुछ अलग है:

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

आप इसे JSBin पर कार्रवाई में देख सकते हैं ।

मैंने अंडरस्कोर में ऐसा कुछ नहीं देखा जो hasकरता है, हालांकि मैं इसे याद कर रहा हूं। यह बहुत समान है _.contains, लेकिन तुलना के _.isEqualबजाय उपयोग करता है ===। इसके अलावा, इस के बाकी समस्या-विशिष्ट है, हालांकि सामान्य होने के प्रयास के साथ।

अब 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आपके द्वारा आपूर्ति किए गए नाम के अनुसार एक संपत्ति के रूप में संग्रहीत किया जाता है और यदि आप केवल एक स्थानीय संदर्भ चाहते हैं तो भी लौटा दिया जाता है।

वैसे यह बहुत स्पष्टीकरण है। कोड यथोचित सीधा है, मुझे उम्मीद है!


नमस्ते .. क्या आप केवल एक मान द्वारा समूह और योग देख सकते हैं, लेकिन यदि मैं value1 और value2 और value3 द्वारा योग चाहता हूं ... तो क्या आपके पास कोई समाधान है?
SAMUEL OSPINA

@SAMUELOSPINA क्या आपको कभी ऐसा करने का तरीका मिला?
HowMuchCheeseIsTooMuchCheese

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) परिणाम एक सरणी नहीं है। (2) लॉश ऑब्जेक्ट (ओं) के परिणाम में "मूल्य" बन गया है।
18:10 बजे mg1075

44

यह संभवतः अधिक आसानी से किया जाता है linq.js, जिसका इरादा जावास्क्रिप्ट में डेमो ( डेमो ) में LINQ का सही कार्यान्वयन है :

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
मुझे नहीं पता कि इसके पास अधिक वोट क्यों नहीं हैं। यह संक्षिप्त, पठनीय (मेरे लिए) है और कुशल दिखता है। यह IE11 पर नहीं उड़ता है , लेकिन रेट्रोफिट बहुत मुश्किल नहीं है ( a.reduce(function(em, e){em.set(e.id, (em.get(e.id)||[]).concat([e]));return em;}, new Map()), लगभग)
unbob


18

आप इसे Alasql JavaScript लाइब्रेरी के साथ कर सकते हैं :

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

इस उदाहरण को jsFiddle पर आज़माएं

BTW: बड़े सरणियों पर (100000 रिकॉर्ड और अधिक) Alasql तेजी से थम Linq। JsPref पर परीक्षण देखें।

टिप्पणियाँ:

  • यहाँ मैंने वर्गाकार कोष्ठक में मान रखा है, क्योंकि VALUE SQL में एक खोजशब्द है
  • मुझे स्ट्रिंग मानों को संख्या प्रकार में बदलने के लिए 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

एमडीएन का यह उदाहरण उनके Array.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

यह समाधान किसी भी मनमाने ढंग से कार्य करता है (कुंजी नहीं) इसलिए यह ऊपर दिए गए समाधानों की तुलना में अधिक लचीला है, और तीर के कार्यों की अनुमति देता है , जो LINQ में उपयोग किए गए लैम्ब्डा अभिव्यक्तियों के समान हैं :

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

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. सबसे पहले, हम एक अरै पास करके एक नया सेट बना रहे हैं। क्योंकि सेट केवल अनन्य मानों की अनुमति देता है, सभी डुप्लिकेट हटा दिए जाएंगे।

  1. अब डुप्लिकेट चले गए हैं, हम इसे फैलाने वाले ऑपरेटर का उपयोग करके एक सरणी में वापस परिवर्तित करने जा रहे हैं ...

सेट डॉक: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set Spread OperatorDoc: https : //developer.mozilla.org-en-US/docs/Wava/JavaScript / संदर्भ / ऑपरेटरों / Spread_syntax


मुझे आपका उत्तर बहुत पसंद है, यह सबसे छोटा है, लेकिन मुझे अभी भी तर्क समझ में नहीं आता है, विशेष रूप से, यहां समूह बनाने वाले कौन हैं? क्या इसका प्रसार ऑपरेटर (...) है? या 'नया सेट ()'? कृपया इसे हमें समझाएं ... धन्यवाद
इवान

1
1. सबसे पहले, हम एक अरै पास करके एक नया सेट बना रहे हैं। क्योंकि सेट केवल अनन्य मानों की अनुमति देता है, सभी डुप्लिकेट हटा दिए जाएंगे। 2. अब डुप्लिकेट चले गए हैं, हम इसे फैलाने वाले ऑपरेटर का उपयोग करके एक सरणी में वापस बदलने जा रहे हैं ... सेट डॉक्टर: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… स्प्रेड ऑपरेटर: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
येगो गेहर

ठीक है, मिल गया ... स्पष्टीकरण के लिए धन्यवाद सर :)
इवान

आपका स्वागत है!
यागो गेह्रेस

6

चेक किया गया उत्तर - सिर्फ उथला समूहन। कम करना बहुत अच्छा है। प्रश्न अतिरिक्त कुल गणना की समस्या भी प्रदान करता है।

यहाँ कुछ फ़ील्ड (1) के साथ ऑब्जेक्ट्स के एरे के लिए एक वास्तविक समूह द्वारा गणना की गई कुंजी नाम और 2) वांछित कुंजी की सूची प्रदान करके समूह की कैस्केडिंग के लिए पूर्ण समाधान है और अपने अद्वितीय मानों को SQL कुंजी जैसे रूट कुंजियों में परिवर्तित कर रहा है। BY करता है।

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],
  }), {});

यहां, हमारा रिड्यूसर आंशिक रूप से गठित रिटर्न वैल्यू (एक खाली ऑब्जेक्ट के साथ शुरू) लेता है, और पिछले रिटर्न वैल्यू के फैल आउट सदस्यों से बना एक ऑब्जेक्ट देता है, साथ ही एक नया सदस्य जिसकी कुंजी की गणना वर्तमान iteree के मूल्य से की जाती है 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 का उपयोग कर समाधान पढ़ना मुश्किल है:

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

पूछ कैसे करता है उन लोगों के लिए भी काम करते हैं, यहां व्याख्या दी गई है:

  • दोनों में =>आपके पास एक स्वतंत्र हैreturn

  • Array.prototype.reduceसमारोह 4 मानकों तक लगते हैं। इसलिए पाँचवाँ पैरामीटर जोड़ा जा रहा है ताकि हम डिफ़ॉल्ट मान का उपयोग करके पैरामीटर घोषणा स्तर पर समूह (k) के लिए एक सस्ता चर घोषणा कर सकें। (हाँ, यह टोना है)

  • यदि हमारा वर्तमान समूह पिछली पुनरावृत्ति पर मौजूद नहीं है, तो हम एक नया खाली सरणी बनाते हैं। ((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
क्या आप इसे थोड़ा समझाना चाहेंगे, यह एकदम सही है
नुवान दम्मिका

@NuwanDammika - दोनों में => आपके पास एक मुफ्त "रिटर्न" है - कम फ़ंक्शन 4 मापदंडों तक ले जाता है। इसलिए पाँचवाँ पैरामीटर जोड़ा जा रहा है, ताकि हमारे पास समूह (k) के लिए एक सस्ता परिवर्तनीय घोषणा हो सके। - यदि पिछले मान में हमारा वर्तमान समूह नहीं है, तो हम एक नया खाली समूह बनाते हैं ((r [k]) || (r [k] = = []) यह बाईं अभिव्यक्ति का मूल्यांकन करेगा, अन्यथा एक सरणी या a खाली सरणी, यही कारण है कि उस अभिव्यक्ति के बाद एक तत्काल धक्का होता है। - जब कोई वापसी होती है, तो अल्पविराम ऑपरेटर सबसे बाएं मूल्य को त्याग देगा, जो कि पिछले पिछले समूह को
लौटाएगा

2

एक जेनेरिक Array.prototype.groupBy()टूल बनाने की सुविधा देता है । बस विविधता के लिए कुछ पुनरावर्ती दृष्टिकोण पर मिलान करने वाले कुछ हास्कलेस्क पैटर्न के लिए ईएस 6 फैन्सीनेस फैलाने वाले ऑपरेटर का उपयोग करें। आइए हम 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

@Mortb, @jmarceli उत्तर से और इस पोस्ट से ,

मैं समूह JSON.stringify()के PRIMITIVE VALUE के कई स्तंभों की पहचान होने का लाभ उठाता हूं ।

बिना थर्ड पार्टी के

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

साथ Lodash तीसरे पक्ष के

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

की -गेटर रिटर्न अपरिभाषित
असबर अली

@AsbarAli मैंने क्रोम के कंसोल के साथ अपने स्निपेट का परीक्षण किया - संस्करण 66.0.3359.139 (आधिकारिक बिल्ड) (64-बिट)। और सब कुछ ठीक चलता है। क्या आप कृपया डिबगिंग ब्रेक पॉइंट डाल सकते हैं और देख सकते हैं कि कीगेटर अपरिभाषित क्यों है। यह, शायद, ब्राउज़र संस्करण की वजह से है।
प्रणिधान टी।

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

मैं घोषणात्मक- js की जाँच groupByकरूँगा कि यह वही है जो आप देख रहे हैं। ये भी:

  • बहुत अच्छा प्रदर्शन (प्रदर्शन बेंचमार्क )
  • टाइपस्क्रिप्ट में लिखा है इसलिए सभी typpings शामिल हैं।
  • यह 3 पार्टी सरणी जैसी वस्तुओं का उपयोग करने के लिए लागू नहीं है।
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

बस स्कॉट Sauyet के जवाब में जोड़ने के लिए , कुछ लोग टिप्पणियों में पूछ रहे थे कि केवल एक मान को समूहीकृत करने के बजाय, अपने फ़ंक्शन को ग्रुपबी मान 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)}
    );
});

मुख्य एक (DataGrouper) को अपरिवर्तित रखना:

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')));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.