ES 6 में ऑब्जेक्ट से कुछ गुण लेने के लिए एक-लाइनर


153

कोई फ़ंक्शन कैसे लिख सकता है, जो ईएस 6 में सबसे कॉम्पैक्ट तरीके से केवल कुछ विशेषताओं को लेता है?

मैं विनाशकारी + सरलीकृत ऑब्जेक्ट शाब्दिक का उपयोग करके समाधान के साथ आया हूं, लेकिन मुझे यह पसंद नहीं है कि फ़ील्ड की सूची कोड में दोहराई गई है।

वहाँ भी एक घिनौना समाधान है?

(v) => {
    let { id, title } = v;
    return { id, title };
}

जवाबों:


124

यहाँ कुछ स्लिमर है, हालांकि यह खेतों की सूची को दोहराने से नहीं रोकता है। यह पैरामीटर की आवश्यकता से बचने के लिए "पैरामीटर विनाशकारी" का उपयोग करता है v

({id, title}) => ({id, title})

(इस अन्य उत्तर में एक ज्वलनशील उदाहरण देखें )।

@ EthanBrown का समाधान अधिक सामान्य है। यहाँ इसका एक अधिक मुहावरेदार संस्करण है जो उपयोग करता है Object.assign, और गणना किए गए गुण ( [p]भाग):

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

यदि हम गुणों के गुणों को संरक्षित करना चाहते हैं, जैसे कि configurableऔर गेटर्स और सेटर, जबकि गैर-गुणांक गुणों को छोड़ना, तब:

function pick(o, ...props) {
    var has = p => o.propertyIsEnumerable(p),
        get = p => Object.getOwnPropertyDescriptor(o, p);

    return Object.defineProperties({},
        Object.assign({}, ...props
            .filter(prop => has(prop))
            .map(prop => ({prop: get(props)})))
    );
}

10
+1 अच्छा जवाब, टोरबाज़ो; मुझे अवगत कराने के लिए धन्यवाद Object.assign; es6 एक क्रिसमस के पेड़ की तरह है, जिसके तहत बहुत सारे उपहार मिलते हैं, मैं अभी भी छुट्टी के महीनों के बाद उपहार पा रहा हूं
एथन ब्राउन

एक त्रुटि मिली: संपत्ति का विवरण एक वस्तु होना चाहिए: अपरिभाषित। यह नहीं होना चाहिए filter(...).map(prop => ({[prop]: get(prop)})))?
अंतहीन

अपने पहले pick()कार्यान्वयन के लिए आप कुछ ऐसा भी कर सकते हैंreturn props.reduce((r, prop) => (r[prop] = o[prop], r), {})
पैट्रिक रॉबर्ट्स

दुर्भाग्य से पिक का संस्करण प्रवाह या टाइपस्क्रिप्ट में सुरक्षित नहीं होगा। यदि आप प्रकार की सुरक्षा चाहते हैं, तो मूल ऑब्जेक्ट के विनाश कार्य के आसपास कोई रास्ता नहीं है, तो प्रत्येक को एक नई वस्तु में असाइन करें।
दुहसेकोह

जब कोई संपत्ति किसी वस्तु में मौजूद नहीं होती है, तो आप प्राप्त करते हैं undefined। कभी-कभी यह मायने रखता है। इसके अलावा, अच्छा विचार है।
x-yuri

43

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

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

तब आपके पास एक आसान पुन: प्रयोज्य कार्य है:

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');

धन्यवाद। यह मेरे सवाल का जवाब नहीं है, लेकिन बहुत अच्छा जोड़ है।
किरिलॉयड

7
(कंधे उचकाने की क्रिया) यह है कि मैं महसूस करता है अपने समाधान के लिए एक जवाब; कोई स्लिमर सामान्य समाधान नहीं है (टोरबाज़ो का समाधान अतिरिक्त क्रिया से हटाता है, लेकिन आवश्यक समस्या है - कि सभी संपत्ति नामों को दो बार लिखना होगा - इसका मतलब है कि यह आपके समाधान से बेहतर नहीं है)। मेरा समाधान कम से कम अच्छी तरह से तराजू ... pickएक बार फ़ंक्शन को सही करें , और आप जितनी चाहें उतने गुण चुन सकते हैं और यह उन्हें दोगुना नहीं करेगा।
एथन ब्राउन

1
आप उपयोग क्यों करते हैं hasOwnProperty ? यदि खेतों को हाथ से चुना जाता है, तो भी inअधिक उपयुक्त प्रतीत होता है; हालाँकि मैं पूरी तरह से चेक को छोड़ने के लिए जाऊँगा और बस उन्हें डिफ़ॉल्ट होने दूंगा undefined
बरगी

बर्गी, यह एक उचित बिंदु है ... मैं अजीब ("बदबूदार" होने के लिए एक प्रोटोटाइप श्रृंखला पर गुणों (तरीकों को नहीं) मानता हूं (जैसा कि वे एक कोड गंध हैं), और मैं उन्हें डिफ़ॉल्ट रूप से फ़िल्टर करना पसंद करता हूं। अगर वहाँ एक आवेदन है कि प्रोटोटाइप गुण की जरूरत है, अच्छी तरह से ... वहाँ के लिए एक विकल्प हो सकता है।
एथेन ब्राउन

json arrays के बारे में क्या!
रिजवान पटेल

19

एक-लाइनर के रूप में इसे हल करने की चाल को लिया गया दृष्टिकोण फ्लिप करना है: मूल वस्तु से शुरू करने के बजाय orig , वे उन चाबियों से शुरू कर सकते हैं जिन्हें वे निकालना चाहते हैं।

Array#reduceएक का उपयोग करके फिर खाली वस्तु पर प्रत्येक आवश्यक कुंजी को संग्रहीत किया जा सकता है जो कि में पारित किया गया हैinitialValue कि उक्त फ़ंक्शन के ।

इस तरह:

const orig = {
  id: 123456789,
  name: 'test',
  description: '…',
  url: 'https://…',
};

const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});

console.log(filtered); // Object {id: 123456789, name: "test"}


11

अल्पविराम ऑपरेटर का उपयोग कर एक छोटा सा छोटा समाधान:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})

console.log(
  pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
)  


इसका उपयोग कैसे करें? क्या आप एक उदाहरण प्रदान कर सकते हैं?
टॉमस एम

1
यह pickइस सूत्र में अन्य कार्यों की तरह ही काम करता है :pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
shesek

8

TC39 का ऑब्जेक्ट रेस्ट / स्प्रेड प्रॉपर्टीज प्रपोजल इसको काफी धीमा बना देगा:

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }

(इसमें वे xऔर yचर बनाने की नकारात्मक स्थिति है, जिनकी आपको आवश्यकता नहीं है।)


33
यह एक सुविधाजनक रूप है omit, लेकिन नहींpick
kirilloid

5
मैं एक ऐसे संस्करण को देखना पसंद करूंगा जो ईएस प्रस्ताव के बिल्कुल विपरीत है:let { a, b } as z = { x: 1, y: 2, a: 3, b: 4 }
gfullam

3

आप मौजूदा ऑब्जेक्ट से गुणों को अनपैक करने के लिए विनाशकारी वस्तु का उपयोग कर सकते हैं और उन्हें अलग-अलग नामों के साथ चर में असाइन कर सकते हैं - एक नए, प्रारंभिक रूप से तैयार की गई वस्तु के क्षेत्र।

const person = {
  fname: 'tom',
  lname: 'jerry',
  aage: 100,
}

let newPerson = {};

({fname: newPerson.fname, lname: newPerson.lname} = person);

console.log(newPerson);


(अनुक्रमणिका): ३६
बिना पढ़ा हुआ वाक्य रचना

@Remzes नहीं जानते कि आप इसे कहाँ और कैसे निष्पादित कर रहे हैं, लेकिन यह SO कोड संपादक और क्रोम डेवलपर टूल में अच्छा काम करता है।
सकाम

मैं jsfiddle इस्तेमाल किया
Remzes

मैंने आपके उत्तर को थोड़ा सुधार दिया है, लेकिन यह अभी भी क्रिया है, बनाम ओपी ने क्या मांगा। यह न केवल फ़ील्ड नामों को दोहराता है, बल्कि नए ऑब्जेक्ट का नाम भी है।
Dan Dascalescu

3

जब प्रश्न लिखा गया था उस समय ES6 नवीनतम कल्पना थी। जैसा कि इस उत्तर में बताया गया है , ES6 की तुलना में ES2019 में कुंजी चुनना काफी कम है:

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)

2

वर्तमान में जावास्क्रिप्ट के ऑब्जेक्ट शॉर्टहैंड सिंटैक्स में सुधार के लिए एक स्ट्रोमैन प्रस्ताव है , जो पुनरावृत्ति के बिना नामित गुणों के "पिकिंग" को सक्षम करेगा:

const source = {id: "68646", genre: "crime", title: "Scarface"};
const target = {};
Object.assign(target, {source.title, source.id});

console.log(picked);
// {id: "68646", title: "Scarface"}

दुर्भाग्य से, प्रस्ताव जल्द ही किसी भी समय कहीं भी नहीं जा रहा है। अंतिम बार जुलाई 2017 में संपादित किया गया और अभी भी स्टेज 0 पर एक मसौदा है , यह सुझाव देते हुए कि लेखक इसके बारे में भूल गया है या भूल सकता है।

ES5 और पहले (गैर-सख्त मोड)

संक्षिप्त रूप से संभव शॉर्टहैंड मैं एक प्राचीन भाषा की सुविधा को शामिल करता हूं जिसके बारे में कोई भी उपयोग नहीं करता है:

Object.assign(target, {...(o => {
    with(o) return { id, title };
})(source)});

withबयान सख्त मोड में निषिद्ध हैं, यह आधुनिक जावास्क्रिप्ट के 99.999% के लिए बेकार है। थोड़ी शर्म की बात है, क्योंकि यह केवल आधा-सभ्य उपयोग है जो मैंने इस withसुविधा के लिए पाया है । 😀


1

मेरे पास एथन ब्राउन के समाधान के समान है, लेकिन इससे भी कम - pickफ़ंक्शन। एक अन्य फ़ंक्शन pick2थोड़ा लंबा (और धीमा) है, लेकिन ES6 तरीके के समान गुणों का नाम बदलने की अनुमति देता है।

const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})

const pick2 = (o, ...props) => props.reduce((r, expr) => {
  const [p, np] = expr.split(":").map( e => e.trim() )
  return p in o ? {...r, [np || p]: o[p]} : r
}, {}) 

यहाँ उपयोग उदाहरण है:

const d = { a: "1", c: "2" }

console.log(pick(d, "a", "b", "c"))        // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }

1
पतन का कारण क्या है? क्या यह आपके लिए काम नहीं करता है?
एलेक्जेंड्रा प्रिज़ेव

0

मुझे इस अतिश्योक्ति की आवश्यकता थी, लेकिन मुझे पता नहीं था कि प्रस्तावित कुंजियाँ उपलब्ध हैं या नहीं। इसलिए, मैंने @torazaburo का उत्तर लिया और अपने उपयोग के मामले में सुधार किया:

function pick(o, ...props) {
  return Object.assign({}, ...props.map(prop => {
    if (o[prop]) return {[prop]: o[prop]};
  }));
}

// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }

0

https://stackoverflow.com/users/865693/shesek के कम दृष्टिकोण से प्रेरित :

const pick = (orig, ...keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})

उपयोग:

pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear') का परिणाम: {model: "F40", productionYear: 1987}

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