2013-02-15 19 views
5

से ऑब्जेक्ट बनाएं यह this question पर एक रिवर्स प्रश्न है।डॉट नोटेशन

एक वस्तु x={a:1,b:2} और एक स्ट्रिंग c.d=3 को देखते हुए, निम्नलिखित के लिए x वस्तु को संशोधित:

{ 
    a:1, 
    b:2, 
    c:{ 
    d:3 
    } 
} 

मैं एक समाधान है कि eval उपयोग नहीं करता है के लिए देख रहा हूँ। उपयोग के मामले इस प्रकार है:

x एक विन्यास वस्तु जा रहा है, हम कहते हैं: config.set("music.shuffle",true)

अब, music.shuffle किसी भी तरह पार्स किया जाना चाहिए और config.set समारोह के अंदर आंतरिक वस्तु x को जोड़ा गया, कि इतने एक्स लग रहा है कि:

x={a:1,b:2,music:{shuffle:true}} 
+0

यदि सी एक स्ट्रिंग है तो आपको इसे किसी ऑब्जेक्ट में आज़माकर मैन्युअल रूप से पार्स करना होगा। मैं लगभग गारंटी दे सकता हूं कि यह करना आसान होगा जहां आप स्ट्रिंग सी बनाते हैं और आपको कोई मैन्युअल पार्सिंग नहीं करना चाहिए। कृपया अपने कोड का यह अनुभाग दिखाएं ताकि मैं – Undefined

+0

की सहायता कर सकूं, क्या स्ट्रिंग 'dot.separated.string = value' होने की गारंटी है और मूल्य पर कौन से प्रतिबंध लगाए गए हैं? क्या यह उदाहरण के लिए एक JSON प्रकार है? –

+0

स्ट्रिंग को dot.seperated होने की गारंटी है, और मूल्य पर कोई बाधा नहीं है। – Nemo

उत्तर

10

मुझे लगता है कि आप इस तरह से कुछ कर सकते हैं मेरे सिर के ऊपर बंद:

function addValueToObj(obj, newProp) { 
    newProp = newProp.split("=");  // separate the "path" from the "value" 

    var path = newProp[0].split("."),  // separate each step in the "path" 
     val = newProp.slice(1).join("="); // allow for "=" in "value" 

    for (var i = 0, tmp = obj; i < path.length - 1; i++) { 
     tmp = tmp[path[i]] = {};  // loop through each part of the path adding to obj 
    } 
    tmp[path[i]] = val;    // at the end of the chain add the value in 
} 

var x = {a:1, b:2}; 
addValueToObj(x, "c.d=3"); 
// x is now {"a":1,"b":2,"c":{"d":"3"}} 
addValueToObj(x, "e.f.g.h=9=9"); 
// x is now {"a":1,"b":2,"c":{"d":"3"},"e":{"f":{"g":{"h":"9=9"}}}} 

डेमो: http://jsfiddle.net/E8dMF/1/

+4

बेशक पूछताछ करने के लिए, लेकिन मैं अद्यतन करने की अनुशंसा करता हूं ताकि आप पहले से मौजूद संपत्तियों को बंद न करें। उदाहरण के लिए, यदि x = {a: {b: 3}} और मैं addValueToObj (x, "a.c = 4") करता हूं तो बी गायब हो जाता है। –

4

मेरा मानना ​​है कि डोजो सेटऑब्जेक्ट जो आप चाहते हैं वह करता है। यदि आप (समझदारी से) सभी डोजो में नहीं खींचना चाहते हैं तो मैं अपने (स्वतंत्र रूप से उपलब्ध) स्रोत की जांच करने या एएमडी के माध्यम से केवल बेस (केवल 4k) लोड करने की अनुशंसा करता हूं।

function setObject(name, value, context) { 
    var parts=name.split("."), 
    p=parts.pop(); 
    for(var i=0, j; context && (j=parts[i]); i++){ 
     context = (j in context ? context[j] : context[j]={}); 
    } 
    return context && p ? (context[p]=value) : undefined; // Object 
} 

तो आपके मामले में आप क्या करेंगे:

x={a:1,b:2}; 
setObject("c.d", 3, x); 

चेतावनी: कुछ इस तरह दिखता है जब तक आप केवल कभी तुच्छ मामलों से निपटने के, मैं तुम्हें आग्रह करता हूं अभी भी पूर्ण की जाँच जाना होगा डोजो कार्यान्वयन, जो मामलों से संबंधित है, जहां कोई संदर्भ आदि

2

प्रदान की जाती है यहाँ एक भारी टिप्पणी की संस्करण है कि कुछ हद तक समझने के लिए सरल होना चाहिए है।

// stores the configured data 
configStore = {}; 

config = { 
    set: function(keyValueString) { 

    // Split the string by the = 
    var pair = keyValueString.split('='); 

    // left of the = is the key path 
    var keyPath = pair[0]; 

    // right of the = is the value to set 
    var value = pair[1]; 

    // split keyPath into an array of keys 
    var keys = keyPath.split('.'); 
    var key; // used in loop 

    // the current level of object we are drilling into. 
    // Starts as the main root config object. 
    var currentObj = configStore; 

    // Loop through all keys in the key path, except the last one (note the -1). 
    // This creates the object structure implied by the key path. 
    // We want to do something different on the last iteration. 
    for (var i=0; i < keys.length-1; i++) { 

     // Get the current key we are looping 
     key = keys[i]; 

     // If the requested level on the current object doesn't exist, 
     // make a blank object. 
     if (typeof currentObj[key] === 'undefined') { 
     currentObj[key] = {}; 
     } 

     // Set the current object to the next level of the keypath, 
     // allowing us to drill in. 
     currentObj = currentObj[key]; 
    } 

    // Our loop doesn't handle the last key, because that's when we 
    // want to set the actual value. So find the last key in the path. 
    var lastKey = keys[keys.length-1] 

    // Set the property of the deepest object to the value. 
    currentObj[lastKey] = value; 
    } 
}; 

// Do it. 
config.set('omg.wtf.bbq=123') 

// Check it. 
alert(configStore.omg.wtf.bbq); // 123 
2

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

कोई सत्यापन, अगर आप इसे बुरा डेटा पास है, तो आप निश्चित रूप से कुंजी के ऊपर लिख सकते हैं।

// @param object orig the object to extend 
// @param array keyParts the.key.path split by "." (expects an array, presplit) 
// @param mixed value the value to assign 
// @param object scoped used by the recursion, ignore or pass null 
function unflatten(orig, keyParts, value, scoped) { 
    if (!scoped) { 
     scoped = orig; 
    } 

    var nextKey = keyParts.shift(); 

    if (keyParts.length === 0) { 
     scoped[nextKey] = value; 
     return orig; 
    } 

    if (!scoped[nextKey]) { 
     scoped[nextKey] = {}; 
    } 

    scoped = scoped[nextKey]; 
    return unflatten(orig, keyParts, value, scoped); 
} 

फ़ंक्शन प्रोटोटाइप में सुधार किया जा सकता है, लेकिन मेरी ज़रूरतों को पूरा करता है। के माध्यम से यह कॉल:

var orig = { foo: 'hello world', bar: { baz: 'goodbye world' } }; 

// lets add the key "bar.cat.aww" with value "meow" 
unflatten(orig, "bar.cat.aww".split("."), "meow"); 
/* 
    orig is { 
    foo: "hello world", 
    bar: { 
     baz: "goodbye world", 
     cat: { 
     aww: "meow" 
     } 
    } 
    } 

*/ 

// we can keep calling it to add more keys 
unflatten(orig, "some.nested.key".split("."), "weeee"); 

/* 
    orig is { 
    foo: "hello world", 
    bar: { 
     baz: "goodbye world", 
     cat: { 
     aww: "meow" 
     } 
    }, 
    some: { 
     nested: { 
     key: "weeee" 
     } 
    } 
    } 
*/ 
0

इस बारे में कैसे के साथ ऐसा कर सकते हैं?

यह किसी मौजूदा ऑब्जेक्ट को बना या कॉपी/ओवरराइट करेगा।

function expando(obj, base) { 
    return Object.keys(obj) 
     .reduce((clone, key) => { 
     key.split('.').reduce((innerObj, innerKey, i, arr) => 
      innerObj[innerKey] = (i+1 === arr.length) ? obj[key] : innerObj[innerKey] || {}, clone) 
     return clone; 
    }, Object.assign({}, base)); 
} 

console.log(expando({'a.b': 1})) // { a: { b : 1 }} 
console.log(expando({'b.c': 2}, { a: 1 })) // { a: 1, b: { c: 2 }} 
console.log(expando({'b.c.d': 2, 'e.f': 3}, { a: 1 })) // { a: 1, b: { c: { d: 2 } }, e: { f: 3}} 

नोट: ES6 तीर कार्यों और Object.assign() के लिए आवश्यक है।

चारों ओर खेलने के लिए स्वतंत्र महसूस:

https://jsbin.com/setazahuce/1/edit?js,console

0

क्या इस बारे में:

function setObj (str, value, obj) { 
    var ref = obj, keys = str.split('.'); 
    while (keys.length) { 
     var currentKey = keys.shift(); 
     ref[currentKey] = keys.length ? (ref[currentKey] ? ref[currentKey] : {}) : value; 
     ref = ref[currentKey]; 
    } 
} 

का उपयोग कर

($ .serializeArray साथ निकाली गई किसी न किसी रूप मूल्यों हो सकता है) एक इनपुट वस्तु के साथ उदाहरण
var serializedInputs = [ 
    {name: 'fruits[1][name]', value: 'Banana'}, 
    {name: 'fruits[1][id]', value: '1'}, 
    {name: 'fruits[2][name]', value: 'Strawberry'}, 
    {name: 'fruits[2][id]', value: '2'}, 
    {name: 'fruits[3][name]', value: 'Raspberry'}, 
    {name: 'fruits[3][id]', value: '3'}, 
    {name: 'fruits[4][name]', value: 'Kiwi'}, 
    {name: 'fruits[4][id]', value: '4'}, 
    {name: 'fruits[5][name]', value: 'Mango'}, 
    {name: 'fruits[5][id]', value: '5'}, 
    {name: 'selected_fruit_id', value: '1'}, 
] 
// This variable holds the result 
var obj = {} 
serializedInputs.forEach(function(item) { 
    // Turning square brackets into dot notation 
    setObj(item.name.replace(/\]/g, '').replace(/\[/g, '.'), item.value, obj); 
}) 

परिणाम

{ 
    "fruits": { 
     "1": { 
      "name": "Banana", 
      "id": "1" 
     }, 
     "2": { 
      "name": "Strawberry", 
      "id": "2" 
     }, 
     "3": { 
      "name": "Raspberry", 
      "id": "3" 
     }, 
     "4": { 
      "name": "Kiwi", 
      "id": "4" 
     }, 
     "5": { 
      "name": "Mango", 
      "id": "5" 
     } 
    }, 
    "selected_fruit_id": "1" 
}