2012-06-11 11 views
5

मेरे पास एक ऑब्जेक्ट है जिसमें सरल एन्कोडिंग/डिकोडिंग के लिए प्रतिस्थापन मूल्यों के जोड़े हैं (सुरक्षा के लिए नहीं, केवल सुविधा के लिए; यहां सभी को समझाने के लिए बहुत जटिल)। यहजावास्क्रिप्ट: ऑब्जेक्ट में त्वरित रूप से लुकअप मान (जैसे हम गुणों के साथ कर सकते हैं)

var obj = {x: y, 
      x: y, 
      ... 
      }; 

जहां 'x' एन्कोड किए जाने पर मान है और 'y' डीकोडेड मान है।

डिकोडिंग सरल है: मैं स्ट्रिंग के पात्रों के माध्यम से लूप करता हूं, और ब्रैकेट के माध्यम से ऑब्जेक्ट में charAt(i) मान को देखता हूं: obj[ str.charAt(i) ]। (मैं यह देखने के लिए चेक छोड़ रहा हूं कि हमें अपरकेस या लोअरकेस संस्करण की आवश्यकता है (ऑब्जेक्ट में सभी कुंजी/मान लोअरकेस हैं), लेकिन यह काफी आसान है।)

एन्कोड करने के लिए, मुझे निश्चित रूप से देखना होगा संपत्ति के बजाय वस्तु में मूल्य। वर्तमान में, मैं for ... in ... लूप के साथ गुणों के माध्यम से लूपिंग कर रहा हूं और charAt(i) मान के विरुद्ध मानों की जांच कर रहा हूं। मेरा वर्तमान कोड है:

var i, j, 
    output = '', 
    str = 'Hello World!', 
    obj = {'s':'d', 
      'm':'e', 
      'e':'h', 
      'x':'l', 
      'z':'o', 
      'i':'r', 
      'a':'w', 
      'o':'!', 
      '-':' '}; 
for (i = 0; i < str.length; i++) { 
    for (j in obj) { 
     if (Object.prototype.hasOwnProperty.call(obj, j) && 
      Object.prototype.propertyIsEnumerable.call(obj, j)) { 
      if (obj[j] === str.charAt(i)) { 
       output += j; 
       break; 
      } else if (obj[j].toUpperCase() === str.charAt(i)) { 
       output += j.toUpperCase(); 
       break; 
      } 
     } 
    } 
} 
alert(output); 

मुझे सहजता से ऐसा लगता है कि ऐसा करने का एक और अधिक प्रभावी तरीका होना चाहिए। (बेशक एक उल्टा वस्तु है, {y: x}, एक विकल्प है। लेकिन अच्छा नहीं।) क्या यह सबसे अच्छा तरीका है, या क्या कोई बेहतर है? संक्षेप में, मुझे var prop = obj[value] करने में सक्षम होना पसंद है जैसे मैं var value = obj[prop] कर सकता हूं।

उत्तर

5

यह पहले से एक रिवर्स नक्शा बनाने के लिए सिर्फ एक बार पाश करने के लिए और अधिक कुशल है: str.length * map.length करने का

var str = "Hello World!", 
    output = '', 
    map = { 
     "s":"d", "m":"e", 
     "e":"h", "x":"l", 
     "z":"o", "i":"r", 
     "a":"w", "o":"!", 
     "-":" " 
    }, 
    reverseMap = {} 

for (j in map){ 
    if (!Object.prototype.hasOwnProperty.call(map, j)) continue 
    reverseMap[map[j]] = j 
} 

output = str.replace(/./g, function(c){ 
    return reverseMap[c] || reverseMap[c.toLowerCase()].toUpperCase() 
}) 

console.log(output) 

इसके बजाय, आप ' map.length + str.length संचालन करेंगे।

+0

हां! यदि मैं कर सकता था, तो मैं आपको दो बार ऊपर उठाना चाहता था, क्योंकि यह दोनों में सुझाए गए सुधारों को जोड़ता है। यह निश्चित रूप से मेरा स्वीकार्य उत्तर है (किसी भी अन्य अद्भुत संस्करण को छोड़कर ...)। धन्यवाद! –

2

आप मैपिंग प्रोग्रामिंग (हाथ से इसके बजाए) का एक उलट संस्करण बना सकते हैं और इसके बजाय इसका उपयोग कर सकते हैं।

var rev = {} 
for (key in obj) 
    rev[obj[key]] = key 
+0

क्या आप जानते हैं? आप एक प्रतिभाशाली हैं ...;) यह मेरे लिए उन "डीयूएच" क्षणों में से एक है। हाथ से मैपिंग निश्चित रूप से एक विकल्प नहीं था, खासकर अगर मैं मूल के दायरे को बढ़ाने में सक्षम होना चाहता हूं। (मैंने कोड देखा है जिसमें काफी लंबे कुंजी/मूल्य जोड़े के दो संस्करण हैं, और मैं सोच रहा हूं कि उन्हें टाइप करने में कितना समय बिताया गया था, और विकसित कोड के रूप में संपादन।) –

0

यदि आप सरणी कुंजी की तलाश में हैं तो यहां जांचें।

https://raw.github.com/kvz/phpjs/master/functions/array/array_keys.js

function array_keys (input, search_value, argStrict) { 
    var search = typeof search_value !== 'undefined', tmp_arr = [], strict = !!argStrict, include = true, key = ''; 

    if (input && typeof input === 'object' && input.change_key_case) { 
     return input.keys(search_value, argStrict); 
    } 

    for (key in input) { 
     if (input.hasOwnProperty(key)) { 
      include = true; 
      if (search) { 
       if (strict && input[key] !== search_value) include = false; 
       else if (input[key] != search_value) include = false; 
      } 
      if (include) tmp_arr[tmp_arr.length] = key; 
     } 
    } 

    return tmp_arr; 
} 
3

एक रिवर्स एनकोडर अधिक मतलब होगा, लेकिन आप सभी hasOwnProperty etc.tests बिना एक समारोह की जगह लिख सकते हैं।

var str= 'Hello World!', 
obj={ 
    's':'d', 
    'm':'e', 
    'e':'h', 
    'x':'l', 
    'z':'o', 
    'i':'r', 
    'a':'w', 
    'o':'!', 
    '-':' ' 
} 
str= str.replace(/./g, function(w){ 
    for(var p in obj){ 
     if(obj[p]=== w) return p; 
     if(obj[p]=== w.toLowerCase()) return p.toUpperCase(); 
    }; 
    return w; 
}); 

दिए गए मान: (स्ट्रिंग) Emxxz-Azixso

+0

मुझे नहीं पता था कि आप पास कर सकते हैं इस तरह की जगह बदलने के लिए एक समारोह! मैं मान रहा हूं कि वर्तमान to_replace मान (/./) फ़ंक्शन को पास कर दिया गया है, इसलिए डब्ल्यू? अधिक सुरुचिपूर्ण और पठनीय संस्करण, मैं निश्चित रूप से इसके बारे में सोचूंगा। –

+0

@kennebec आपको प्रोटोटाइप एक्सटेंशन से अपर्याप्त डेटा से बचने के लिए अभी भी 'हैऑनप्रॉपर्टी' चेक की आवश्यकता है। घोषित मूल्य उन्हें ओवरराइड करेंगे, लेकिन जब कोई नहीं था तो त्रुटि उत्पन्न करने के बजाय यह एक मैच वापस कर सकता था। –

+0

@kennebec: मैं उस पर रिकार्डो से सहमत हूं। भले ही यह सब कोड है, मैं खुद को लिख रहा हूं, हमेशा माफी से सुरक्षित होना बेहतर है। और मुझे खुद को अच्छी आदतें मिलना पसंद है।मुझे लगता है कि 'हैऑनप्रोपर्टी' पर्याप्त होना चाहिए। मेरे पास 'propertyInumerable' कारण था [इस जानकारी को वांछित जावास्क्रिप्ट से] [http://eloquentjavascript.net/chapter8.html#p51c5b387)। –

संबंधित मुद्दे