वस्तुओं के एक सरणी से, सरणी के रूप में एक संपत्ति का मूल्य निकालें


1016

निम्नलिखित संरचना के साथ मेरे पास जावास्क्रिप्ट ऑब्जेक्ट सरणी है:

objArray = [ { foo: 1, bar: 2}, { foo: 3, bar: 4}, { foo: 5, bar: 6} ];

मैं प्रत्येक ऑब्जेक्ट से एक फ़ील्ड निकालना चाहता हूं, और एक सरणी प्राप्त करता हूं जिसमें मान होते हैं, उदाहरण के लिए फ़ील्ड fooसरणी देगा [ 1, 3, 5 ]

मैं इस तुच्छ दृष्टिकोण के साथ ऐसा कर सकता हूं:

function getFields(input, field) {
    var output = [];
    for (var i=0; i < input.length ; ++i)
        output.push(input[i][field]);
    return output;
}

var result = getFields(objArray, "foo"); // returns [ 1, 3, 5 ]

क्या ऐसा करने के लिए अधिक सुरुचिपूर्ण या मुहावरेदार तरीका है, ताकि एक कस्टम उपयोगिता फ़ंक्शन अनावश्यक हो?


सुझाए गए डुप्लिकेट के बारे में ध्यान दें , यह किसी एकल ऑब्जेक्ट को किसी सरणी में बदलने के लिए कैसे कवर करता है ।


3
प्रोटोटाइप लाइब्रेरी ने ऐरे प्रोटोटाइप (मुझे लगता है) में एक "प्लक" फ़ंक्शन जोड़ा, ताकि आप लिख सकें var foos = objArray.pluck("foo");
नुकीले

3
@id - jsperf.com/map-vs-native-for-loop - कृपया इस पर एक नज़र है, आशा है कि सादा स्वयं एक अच्छा समाधान
पाकर

1
@ N20084753 एक निष्पक्ष परीक्षण के लिए आपको मूल Array.prototype.mapकार्य की तुलना करनी चाहिए जहाँ यह मौजूद है
अलनीतक

@Alnitak - फिर आप सही हैं लेकिन मैं यह नहीं समझ सकता कि देशी Array.prototype.map को लूप के लिए देशी की तुलना में कैसे ऑप्टिमाइज़ किया जाता है, किसी भी तरह से हमें पूर्ण सरणी को ट्रैवस करना होगा।
N20084753

3
ओपी, मैं सुझाव दिया गया है कि किसी भी अन्य के लिए अपने दृष्टिकोण पसंद करते हैं। इसमें कुछ भी गलत नहीं है।

जवाबों:


1334

यहाँ इसे प्राप्त करने का एक छोटा तरीका है:

let result = objArray.map(a => a.foo);

या

let result = objArray.map(({ foo }) => foo)

आप भी देख सकते हैं Array.prototype.map()


3
खैर, यह totymedli द्वारा एक और उत्तर की टिप्पणी के रूप में ही है, लेकिन कोई भी नहीं यह वास्तव में बेहतर (मेरी राय में) अन्य उत्तरों की तुलना में बेहतर है , इसलिए ... इसे स्वीकार किए गए उत्तर में बदलना।
हाइड


1
यकीन है, इसकी अनुमति है, लेकिन IMHO कुछ भी नहीं है जो इस उत्तर को उद्देश्यपूर्ण रूप से बेहतर बनाता है, सिवाय इसके कि यह एक वाक्यविन्यास का उपयोग करता है जो उस समय उपलब्ध नहीं था जब आपने प्रश्न पूछा था और कुछ ब्राउज़रों में भी समर्थित नहीं है। मैं यह भी नोट करूंगा कि यह उत्तर टिप्पणियों की एक सीधी प्रति है जो इस उत्तर को पोस्ट करने से लगभग एक साल पहले मूल रूप से स्वीकृत उत्तर पर की गई थी।
अलनीतक

26
देखने की मेरी बात में नए कार्यक्षमता का उपयोग करना, @Alnitak, है निष्पक्ष बेहतर। यह स्निपेट बेहद आम है, इसलिए मुझे यकीन नहीं है कि यह साहित्यिक चोरी है। शीर्ष पर पिन किए गए पुराने उत्तरों को रखने में वास्तव में कोई मूल्य नहीं है।
रोब

6
टिप्पणियाँ उत्तर नहीं हैं, यदि कोई किसी उत्तर के बजाय एक टिप्पणी पोस्ट करता है, तो यह उनकी अपनी गलती है यदि कोई इसे उत्तर में कॉपी करता है।
असितत्व

618

हां, लेकिन यह जावास्क्रिप्ट के ईएस 5 फीचर पर निर्भर करता है। इसका मतलब यह IE8 या पुराने में काम नहीं करेगा।

var result = objArray.map(function(a) {return a.foo;});

ES6 संगत JS दुभाषियों पर आप संक्षिप्तता के लिए एक तीर फ़ंक्शन का उपयोग कर सकते हैं :

var result = objArray.map(a => a.foo);

Array.prototype.map प्रलेखन


5
यह समाधान साफ-सुथरा और सरल लगता है, लेकिन क्या यह सादे लूपिंग विधि की तुलना में अनुकूलित है।
N20084753

क्या ओपी किसी भी क्षेत्र को प्राप्त करने के लिए एक विधि नहीं चाहता , न कि केवल हार्डकोड foo?
अलनीतक

2
ES6 में आप कर सकते हैंvar result = objArray.map((a) => (a.foo));
ब्लैक

28
@ बैकलैक और भी बेहतर:var result = objArray.map(a => a.foo);
टोटमेडली 13

4
@FaizKhan वर्ष को नोटिस करें। यह उत्तर 25 अक्टूबर, 2013 को पोस्ट किया गया था। 11 अक्टूबर 2017 को "स्वीकृत" उत्तर पोस्ट किया गया था। यदि ऐसा कुछ उल्लेखनीय है, तो चेकमार्क दूसरे पर चला गया।
नीट द डार्क एबसोल

52

की जाँच करें Lodash के_.pluck() समारोह या अंडरस्कोर के_.pluck() कार्य करते हैं। दोनों बिल्कुल वही करते हैं जो आप सिंगल फंक्शन कॉल में चाहते हैं!

var result = _.pluck(objArray, 'foo');

अद्यतन: नीट के उत्तर के समान कुछ के साथ संयोजन के पक्ष में, _.pluck()लॉडश v4.0.0 के रूप में हटा दिया गया हैअभी भी अंडरस्कोर में उपलब्ध है_.map()_.pluck()

अद्यतन 2: जैसा कि मार्क टिप्पणियों में बताते हैं , कहीं न कहीं लोदश v4 और 4.3 के बीच, एक नया फ़ंक्शन जोड़ा गया है जो इस कार्यक्षमता को फिर से प्रदान करता है। _.property()एक शॉर्टहैंड फ़ंक्शन है जो किसी ऑब्जेक्ट में एक संपत्ति का मूल्य प्राप्त करने के लिए एक फ़ंक्शन देता है।

इसके अतिरिक्त, _.map()अब एक स्ट्रिंग को दूसरे पैरामीटर के रूप में पारित करने की अनुमति देता है, जिसे पास किया जाता है _.property()। नतीजतन, निम्नलिखित दो पंक्तियाँ पूर्व-लोदाश 4 से ऊपर के कोड नमूने के बराबर हैं।

var result = _.map(objArray, 'foo');
var result = _.map(objArray, _.property('foo'));

_.property(), और इसलिए _.map(), आपको उप-संपत्तियों तक पहुंचने के लिए एक डॉट-अलग स्ट्रिंग या सरणी प्रदान करने की भी अनुमति देता है:

var objArray = [
    {
        someProperty: { aNumber: 5 }
    },
    {
        someProperty: { aNumber: 2 }
    },
    {
        someProperty: { aNumber: 9 }
    }
];
var result = _.map(objArray, _.property('someProperty.aNumber'));
var result = _.map(objArray, _.property(['someProperty', 'aNumber']));

_.map()उपरोक्त उदाहरण में दोनों कॉल वापस आएंगे [5, 2, 9]

यदि आप कार्यात्मक प्रोग्रामिंग में थोड़ा अधिक हैं, तो रामदा के R.pluck() कार्य पर एक नज़र डालें , जो कुछ इस तरह दिखाई देगा:

var result = R.pluck('foo')(objArray);  // or just R.pluck('foo', objArray)

5
अच्छी खबर: कहीं-कहीं लोदाश 4.0.0 और 4.3.0 _.property('foo')( lodash.com/docs#property ) को शॉर्टहैंड के रूप में जोड़ा गया function(o) { return o.foo; }। यह लॉडश उपयोग के मामले को var result = _.pluck(objArray, _.property('foo'));आगे की सुविधा के लिए छोटा कर देता है, लॉडश 4.3.0 की _.map() विधि_.property() हुड के नीचे एक शॉर्टहैंड का उपयोग करने की भी अनुमति देती है , जिसके परिणामस्वरूपvar result = _.map(objArray, 'foo');
मार्क ए। फिट्जगेराल्ड

45

जेएस केवल समाधानों के लिए बोलते हुए, मैंने पाया है कि, असमान रूप में यह हो सकता है, एक साधारण अनुक्रमित forलूप अपने विकल्पों की तुलना में अधिक प्रदर्शनशील है।

100000 तत्व सरणी (jsPerf के माध्यम से) से एकल संपत्ति निकालना

लूप 368 ऑप्स / सेक के लिए पारंपरिक

var vals=[];
for(var i=0;i<testArray.length;i++){
   vals.push(testArray[i].val);
}

ES6 for..of लूप 303 ऑप्स / सेक

var vals=[];
for(var item of testArray){
   vals.push(item.val); 
}

Array.prototyp.map 19 ऑप्स / सेक

var vals = testArray.map(function(a) {return a.val;});

TL, DR - .map () धीमा है, लेकिन अगर आपको लगता है कि प्रदर्शन से अधिक मूल्य की पठनीयता है, तो इसका उपयोग करने के लिए स्वतंत्र महसूस करें।

# 2 संपादित करें: 6/2019 - jsPerf लिंक टूट गया, हटा दिया गया।


1
आपको जो पसंद है, उसे कॉल करें, लेकिन प्रदर्शन मायने रखता है। यदि आप मानचित्र को समझ सकते हैं तो आप लूप के लिए समझ सकते हैं।
इलक्रक्स

हालांकि यह आपके बेंचमार्किंग परिणामों के बारे में जानने के लिए उपयोगी है, मुझे लगता है कि यह यहाँ अनुचित है, क्योंकि यह इस प्रश्न का उत्तर नहीं देता है। इसे सुधारने के लिए, या तो एक वास्तविक उत्तर जोड़ें, या फिर इसे एक टिप्पणी (यदि संभव हो) में संपीड़ित करें।
इफेडि ओकोंकोव

15

का उपयोग कर Array.prototype.map:

function getFields(input, field) {
    return input.map(function(o) {
        return o[field];
    });
}

पूर्व-ईएस 5 ब्राउज़रों के लिए एक शिम के लिए उपरोक्त लिंक देखें।


15

क्रॉस ब्राउज़र आश्वासन के लिए किसी प्रकार के पुस्तकालयों का उपयोग करना बेहतर है जैसे कि लॉश या अंडरस्कोर।

लॉडश में आप निम्न विधि से सरणी में एक संपत्ति के मूल्यों को प्राप्त कर सकते हैं

_.map(objArray,"foo")

और अंडरस्कोर में

_.pluck(objArray,"foo")

दोनों लौट आएंगे

[1, 2, 3]

10

ES6 में, आप कर सकते हैं:

const objArray = [{foo: 1, bar: 2}, {foo: 3, bar: 4}, {foo: 5, bar: 6}]
objArray.map(({ foo }) => foo)

क्या हुआ अगर फू अपरिभाषित है? अपरिभाषित की एक सरणी अच्छा नहीं है।
गोधर

6

जबकि mapवस्तुओं की एक सूची से 'कॉलम' का चयन करने के लिए एक उचित समाधान है, यह एक नकारात्मक पक्ष यह है। यदि यह स्पष्ट रूप से जाँच नहीं किया गया है कि कॉलम मौजूद है या नहीं, तो यह एक त्रुटि फेंक देगा और (सबसे अच्छा) आपको प्रदान करेगा undefined। मैं एक reduceसमाधान का विकल्प चुनूंगा , जो केवल संपत्ति की उपेक्षा कर सकता है या यहां तक ​​कि आपको डिफ़ॉल्ट मान के साथ सेट कर सकता है।

function getFields(list, field) {
    //  reduce the provided list to an array only containing the requested field
    return list.reduce(function(carry, item) {
        //  check if the item is actually an object and does contain the field
        if (typeof item === 'object' && field in item) {
            carry.push(item[field]);
        }

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbin उदाहरण

यह तब भी काम करेगा जब प्रदान की गई सूची में से कोई एक वस्तु नहीं है या इसमें फ़ील्ड शामिल नहीं है।

यह भी अधिक लचीला बनाया जा सकता है एक डिफ़ॉल्ट मूल्य पर बातचीत करके एक वस्तु एक वस्तु नहीं होनी चाहिए या फ़ील्ड में शामिल नहीं होनी चाहिए।

function getFields(list, field, otherwise) {
    //  reduce the provided list to an array containing either the requested field or the alternative value
    return list.reduce(function(carry, item) {
        //  If item is an object and contains the field, add its value and the value of otherwise if not
        carry.push(typeof item === 'object' && field in item ? item[field] : otherwise);

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbin उदाहरण

यह मानचित्र के साथ समान होगा, क्योंकि लौटे हुए सरणी की लंबाई प्रदान की गई सरणी के समान होगी। (जो मामले में एक mapसे थोड़ा सस्ता है reduce):

function getFields(list, field, otherwise) {
    //  map the provided list to an array containing either the requested field or the alternative value
    return list.map(function(item) {
        //  If item is an object and contains the field, add its value and the value of otherwise if not
        return typeof item === 'object' && field in item ? item[field] : otherwise;
    }, []);
}

jsbin उदाहरण

और फिर सबसे लचीला समाधान है, जो आपको वैकल्पिक मूल्य प्रदान करके दोनों व्यवहारों के बीच स्विच करने देता है।

function getFields(list, field, otherwise) {
    //  determine once whether or not to use the 'otherwise'
    var alt = typeof otherwise !== 'undefined';

    //  reduce the provided list to an array only containing the requested field
    return list.reduce(function(carry, item) {
        //  If item is an object and contains the field, add its value and the value of 'otherwise' if it was provided
        if (typeof item === 'object' && field in item) {
            carry.push(item[field]);
        }
        else if (alt) {
            carry.push(otherwise);
        }

        //  return the 'carry' (which is the list of matched field values)
        return carry;
    }, []);
}

jsbin उदाहरण

जैसा कि ऊपर दिए गए उदाहरण (उम्मीद है) इस काम के तरीके पर कुछ प्रकाश डालते हैं, फ़ंक्शन को उपयोग करके Array.concatफ़ंक्शन को थोड़ा छोटा करते हैं ।

function getFields(list, field, otherwise) {
    var alt = typeof otherwise !== 'undefined';

    return list.reduce(function(carry, item) {
        return carry.concat(typeof item === 'object' && field in item ? item[field] : (alt ? otherwise : []));
    }, []);
}

jsbin उदाहरण


6

सामान्य तौर पर, यदि आप ऑब्जेक्ट मानों को एक्सट्रपलेशन करना चाहते हैं, जो किसी सरणी के अंदर हैं (जैसे कि प्रश्न में वर्णित है), तो आप कम, नक्शा और सरणी विनाशकारी का उपयोग कर सकते हैं।

ES6

let a = [{ z: 'word', c: 'again', d: 'some' }, { u: '1', r: '2', i: '3' }];
let b = a.reduce((acc, obj) => [...acc, Object.values(obj).map(y => y)], []);

console.log(b)

लूप के लिए उपयोग करने वाला समान होगा:

for (let i in a) {
  let temp = [];
  for (let j in a[i]) {
    temp.push(a[i][j]);
  }
  array.push(temp);
}

उत्पादित आउटपुट: ["शब्द", "फिर से", "कुछ", "1", "2", "3"]


3

यह "बेहतर" की आपकी परिभाषा पर निर्भर करता है।

अन्य उत्तर मानचित्र के उपयोग को इंगित करते हैं, जो कि स्वाभाविक है (विशेष रूप से कार्यात्मक शैली के लिए इस्तेमाल किए गए लोगों के लिए) और संक्षिप्त। मैं दृढ़ता से इसका उपयोग करने की सलाह देता हूं (यदि आप कुछ IE8- आईटी लोगों के साथ परेशान नहीं करते हैं)। तो अगर "बेहतर" का अर्थ है "अधिक संक्षिप्त", "बनाए रखने योग्य", "समझने योग्य" तो हाँ, यह बेहतर है।

दूसरी ओर, यह सुंदरता अतिरिक्त लागत के बिना नहीं आती है। मैं माइक्रोबेनच का बहुत बड़ा प्रशंसक नहीं हूं, लेकिन मैंने यहां एक छोटा परीक्षण किया है । परिणाम पूर्वानुमेय है, पुराना बदसूरत तरीका मानचित्र फ़ंक्शन की तुलना में तेज़ लगता है। तो अगर "बेहतर" का अर्थ "तेज" है, तो नहीं, पुराने स्कूल फैशन के साथ रहें।

फिर से यह सिर्फ एक माइक्रोबैन्च है और किसी भी तरह से इसके इस्तेमाल की वकालत नहीं कर रहा है map, यह सिर्फ मेरा दो सेंट है :)।


खैर, यह वास्तव में सर्वर साइड है, एक ब्राउज़र में नहीं है, इसलिए IE8 अप्रासंगिक है। हां, जाने mapका सबसे अजीब तरीका है, किसी तरह मैं इसे Google के साथ खोजने में विफल रहा (मुझे सिर्फ jquery का नक्शा मिला, जो प्रासंगिक नहीं है)।
हायड

3

यदि आप भी सरणी जैसी वस्तुओं का समर्थन करना चाहते हैं, तो Array.from (ES2015) का उपयोग करें :

Array.from(arrayLike, x => x.foo);

Array.prototype.map () विधि पर इसका लाभ यह है कि इनपुट सेट भी हो सकता है :

let arrayLike = new Set([{foo: 1}, {foo: 2}, {foo: 3}]);

2

यदि आप ES6 + में कई मान चाहते हैं तो निम्नलिखित काम करेगा

objArray = [ { foo: 1, bar: 2, baz: 9}, { foo: 3, bar: 4, baz: 10}, { foo: 5, bar: 6, baz: 20} ];

let result = objArray.map(({ foo, baz }) => ({ foo, baz }))

यह {foo, baz}बाईं ओर के रूप में काम करता है वस्तु विनाशकारी का उपयोग कर रहा है और तीर के दाईं ओर ES6 के बढ़े हुए वस्तु शाब्दिक के{foo: foo, baz: baz} कारण बराबर है


बस मुझे क्या चाहिए, आपको लगता है कि यह समाधान कितना तेज / धीमा है?
रुबेन

1
@ रूबेन वास्तव में यह बताने के लिए कि आपको इस पृष्ठ से विभिन्न विकल्पों को लेने की आवश्यकता है और jsperf.com
क्रिस मैग्नसन

1

ऑब्जेक्ट सरणियों के साथ काम करते समय फ़ंक्शन मैप एक अच्छा विकल्प है। यद्यपि पहले से ही कई अच्छे उत्तर पोस्ट किए गए हैं, फ़िल्टर के साथ संयोजन के साथ मानचित्र का उपयोग करने का उदाहरण सहायक हो सकता है।

यदि आप उन संपत्तियों को बाहर करना चाहते हैं, जो मूल्य अपरिभाषित हैं या सिर्फ एक विशिष्ट संपत्ति को बाहर करते हैं, तो आप निम्नलिखित कार्य कर सकते हैं:

    var obj = {value1: "val1", value2: "val2", Ndb_No: "testing", myVal: undefined};
    var keysFiltered = Object.keys(obj).filter(function(item){return !(item == "Ndb_No" || obj[item] == undefined)});
    var valuesFiltered = keysFiltered.map(function(item) {return obj[item]});

https://jsfiddle.net/ohea7mgk/


0

उपर्युक्त उत्तर एकल संपत्ति निकालने के लिए अच्छा है, यदि आप वस्तुओं के सरणी से एक से अधिक संपत्ति निकालना चाहते हैं तो क्या होगा। यहाँ समाधान है !! उस स्थिति में हम केवल _.पिक (ऑब्जेक्ट, [पथ]) का उपयोग कर सकते हैं

_.pick(object, [paths])

मान लेते हैं कि obrArray में नीचे की तरह तीन गुण हैं

objArray = [ { foo: 1, bar: 2, car:10}, { foo: 3, bar: 4, car:10}, { foo: 5, bar: 6, car:10} ];

अब हम प्रत्येक वस्तु से फू और बार संपत्ति निकालना चाहते हैं और उन्हें एक अलग सरणी में संग्रहीत करते हैं। पहले हम मानचित्र का उपयोग करके सरणी तत्वों को पुनरावृत्त करेंगे और फिर हम उस पर Lodash Library Standard _.pick () विधि लागू करेंगे।

अब हम 'फू' और 'बार' संपत्ति निकालने में सक्षम हैं।

var newArray = objArray.map((element)=>{ return _.pick(element, ['foo','bar'])}) console.log(newArray);

और परिणाम होगा [{फू: 1, बार: 2}, {फू: 3, बार: 4}, {फू: 5, बार: 6}]

का आनंद लें!!!


1
कहाँ _.pickसे आता है? यह एक मानक कार्य नहीं है।
नवमी

मैंने अभी जवाब दिया, _.pick () लोदाश लाइब्रेरी का एक मानक तरीका है।
आकाश जैन

0

यदि आपके पास नेस्टेड ऐरे है तो आप इसे इस तरह से काम कर सकते हैं:

const objArray = [ 
     { id: 1, items: { foo:4, bar: 2}},
     { id: 2, items: { foo:3, bar: 2}},
     { id: 3, items: { foo:1, bar: 2}} 
    ];

    let result = objArray.map(({id, items: {foo}}) => ({id, foo}))
    
    console.log(result)

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