मुख्य बनाम मूल्य जोड़े के लिए जावास्क्रिप्ट में ऑब्जेक्ट बनाम सरणियाँ


83

कहो कि आपके पास एक बहुत ही सरल डेटा संरचना है:

(personId, name)

... और आप इनमें से कई को एक जावास्क्रिप्ट चर में संग्रहीत करना चाहते हैं। जैसा कि मैंने देखा कि आपके पास तीन विकल्प हैं:

// a single object
var people = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

// or, an array of objects
var people = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

// or, a combination of the two
var people = {
    1 : { id: 1, name: 'Joe'},
    3 : { id: 3, name: 'Sam'},
    8 : { id: 8, name: 'Eve'}
};

दूसरा या तीसरा विकल्प स्पष्ट रूप से जाने का तरीका है यदि आपके पास (या उम्मीद है कि आपके पास) स्टोर करने के लिए एक से अधिक "मूल्य" भाग हो सकता है (जैसे, उनकी उम्र या कुछ में जोड़ना), इसलिए, तर्क के लिए, आइए मान लें कि इस संरचना में कभी भी अधिक डेटा मूल्यों की आवश्यकता नहीं है। आप किसे चुनते हैं और क्यों?


संपादित करें : उदाहरण अब सबसे सामान्य स्थिति दिखाता है: गैर-अनुक्रमिक आईडी।


1
इसके अलावा एक 2d सरणी है: var people = [[1, 'Joe'],[3, 'Sam'],[8,'Eve']];(जो आपको आईडी द्वारा फास्ट लुक-अप नहीं देता है, लेकिन डेटा को संग्रहीत करने के लिए एक और विकल्प है)
उपयोगकर्ता

जवाबों:


58

प्रत्येक समाधान के अपने उपयोग के मामले हैं।

मुझे लगता है कि पहला समाधान अच्छा है यदि आप एक-से-एक संबंध (जैसे एक साधारण मानचित्रण) को परिभाषित करने की कोशिश कर रहे हैं, खासकर यदि आपको कुंजी को लुकअप कुंजी के रूप में उपयोग करने की आवश्यकता है।

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

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

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


1
वहाँ अपने तीसरे बिंदु पर। उस समस्या से बचने के लिए वस्तुओं के गुणों को ब्रैकेट नोटेशन में पहुँचा जा सकता है: var x = {"ab> c ++": "foo"}; चेतावनी (एक्स [ 'अब> c ++']);
निक

आपको गुणों के साथ कुछ आरक्षित शब्दों की समस्या है, मुझे विश्वास है। लेकिन जब आप संख्याओं का उपयोग कर रहे हैं तो कोई समस्या नहीं है।
derobert

4
@derobert: मुझे ऐसा नहीं लगता। x = {"डिलीट": 1, "फॉर": 2, "फंक्शन": 3}; - यह वैध है और इसे उसी तरह एक्सेस किया जा सकता है।
निकफ 27'09

7

वास्तव में, एक चौथा विकल्प है:

var people = ['Joe', 'Sam', 'Eve'];

चूँकि आपके मूल्य निरंतर होते हैं। (बेशक, आपको एक को जोड़ना / घटाना होगा --- या पहले तत्व के रूप में अपरिभाषित रखना होगा)।

व्यक्तिगत रूप से, मैं आपके (1) या (3) के साथ जाऊंगा, क्योंकि वे किसी व्यक्ति को आईडी (ओ लॉग एन सबसे खराब) देखने के लिए सबसे तेज होंगे । यदि आपको आईडी 3 इन (2) ढूंढनी है, तो आप या तो इसे इंडेक्स द्वारा देख सकते हैं (जिस स्थिति में मेरा (4) ठीक है) या आपको खोजना होगा - ओ (एन)।

स्पष्टता: मैं कहता हूं कि O (log n ) सबसे खराब है क्योंकि यह AFAIK और कार्यान्वयन हैश तालिका के बजाय एक संतुलित पेड़ का उपयोग करने का निर्णय ले सकता है। एक हैश तालिका न्यूनतम टकराव मानकर O (1) होगी।

निकफ से संपादित करें: मैंने ओपी में उदाहरण बदल दिया है, इसलिए यह उत्तर किसी भी अधिक समझ में नहीं आ सकता है। क्षमा याचना।

इसे पोस्ट किया

ठीक है, संपादित करें, मैं विकल्प चुनूंगा (3)। यह एक्स्टेंसिबल है (नई विशेषताओं को जोड़ना आसान है), तेज लुकअप की सुविधा है, और साथ ही इसे पुनरावृत्त किया जा सकता है। यह आपको प्रवेश आईडी से आईडी तक जाने की अनुमति देता है, क्या आपको इसकी आवश्यकता होनी चाहिए।

विकल्प (1) उपयोगी होगा यदि (ए) आपको मेमोरी बचाने की आवश्यकता है; (b) आपको कभी भी ऑब्जेक्ट से आईडी पर जाने की आवश्यकता नहीं है; (c) आप संग्रहीत डेटा का विस्तार कभी नहीं करेंगे (जैसे, आप व्यक्ति का अंतिम नाम नहीं जोड़ सकते)

विकल्प (2) अच्छा है अगर आपको (ए) को ऑर्डर को संरक्षित करने की आवश्यकता है; (बी) सभी तत्वों को पुनरावृत्त करने की आवश्यकता है; (ग) आईडी द्वारा तत्वों को देखने की आवश्यकता नहीं है, जब तक कि यह आईडी द्वारा सॉर्ट नहीं किया जाता है (आप ओ (लॉग एन ) में एक द्विआधारी खोज कर सकते हैं । ध्यान दें, निश्चित रूप से, यदि आपको इसे क्रमबद्ध रखने की आवश्यकता है, तो आप भुगतान करेंगे। डालने पर एक लागत।


मैं समझता हूं कि क्यों (1) और (3) तब (2) तेज होते हैं, लेकिन मैं सोच रहा हूं कि आपको समय के लिए ओ (लॉग (एन) कैसे मिला? क्या यह O (1) नहीं होना चाहिए क्योंकि आईडी को हैश तालिका में संग्रहीत किया जाना चाहिए?
नथानिएल रेनहार्ट

मैंने लॉग एन को सबसे खराब दिया, क्योंकि मैं हैश टेबल के बजाय एक संतुलित पेड़ का उपयोग करने का निर्णय लेने वाला एक कार्यान्वयन देख सकता था। एक हैश टेबल O (1) होगा [मान लेना टकराव न्यूनतम हैं], बिल्कुल।
derobert

आईडी हमेशा की तरह सरल नहीं हैं और वे शायद ही कभी क्रमिक IRL होंगे, यही कारण है कि आपको उन्हें निर्दिष्ट करने की आवश्यकता है। मैं मानता हूँ कि यह एक गरीब / अस्पष्ट उदाहरण था।
निक

+1, आपका उत्तर स्वीकार किए गए से भी बदतर नहीं है ... लेकिन आपका चौथा समाधान सभी डेटा को संग्रहीत नहीं करता है, इसलिए यहां सही चौथा विकल्प है: var people = []; people[1] = 'Joe'; people[3] = 'Sam'; people[8] = 'Eve';या दो-आयामी सरणी के रूप में: var people = []; people[1] = ['Joe', 'Smith']; people[3] = ['Sam', 'Miller']; people[8] = ['Eve', 'Sweet'];(उदाहरण के लिए लोगों द्वारा एक्सेस किया जाएगा] 3] [1]; 'जो किसी भी वर्ग के अंदर तेज आंतरिक डेटा भंडारण के लिए बहुत अच्छी तरह से काम करता है - अच्छी तरह से, कक्षा के साथ मेरा मतलब है "नया जोफंक्शन ();" वह चीज़ जो जावास्क्रिप्ट को पसंद नहीं है, मैं करता हूं; -) ...
मार्कस

... लेकिन यह केवल तभी काम करता है यदि आईडी एक पूर्णांक है, अन्यथा "क्लासिक" समाधान 2 (एक साथ for(var key in object)पहुंच के लिए प्रसिद्ध ) सामान्य मामलों में जाने का तरीका है (इसमें O (n / 2)), या समाधान है 3 अगर आपके पास तेजी से पहुंच के लिए एक बहुत बड़ा सरणी है, क्योंकि इसमें O (1) है ... और अंत में चलो उपरोक्त समाधान 1 के बारे में भूल जाएं, न केवल अगर आपकी आईडी एक पूर्णांक है, बल्कि यह भी है कि आईडी पूर्णांक नहीं है: var people = {'Smith':'Joe', 'Miller':'Sam', 'Sweet': 'Eve' };( क्योंकि आपको अपनी वस्तु को इस तरह से एक्सेस करने की आवश्यकता होगी: alert(people.Smith);जो वास्तव में अच्छा नहीं है!)।
मार्कस

2

यह मानते हुए कि डेटा कभी नहीं बदलेगा, पहला (एकल ऑब्जेक्ट) विकल्प सबसे अच्छा है।

संरचना की सादगी का अर्थ है यह पार्स करने के लिए सबसे तेज है, और इस तरह के एक के रूप में छोटे, शायद ही कभी (या कभी नहीं) बदलते डेटा सेट के मामले में, मैं केवल कल्पना कर सकता हूं कि इसे अक्सर निष्पादित किया जाएगा - जिस स्थिति में न्यूनतम ओवरहेड है जाने के लिए रास्ता।


2

मैंने मुख्य मूल्य जोड़े का प्रबंधन करने के लिए थोड़ी सी लाइब्रेरी बनाई।

https://github.com/scaraveos/keyval.js#readme

यह उपयोगकर्ता है

  • कुंजी को संग्रहीत करने के लिए एक वस्तु, जो तेजी से हटाने और पुनर्प्राप्ति के संचालन और मूल्य के लिए अनुमति देता है
  • लिंक की गई सूची वास्तव में तेजी से मूल्य पुनरावृत्ति के लिए अनुमति देने के लिए

आशा है कि इससे सहायता मिलेगी :)


jsperf लिंक क्यों नहीं जोड़ते?
जानूस ट्रॉल्सन

वह पुस्तकालय बहुत बढ़िया है। बस मुझे समय का एक गुच्छा बचाया।
क्रिस होफ

1

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

तीसरा पैटर्न आपको आईडी के रूप में किसी भी स्ट्रिंग का उपयोग करने का विकल्प देता है, जटिल व्यक्ति संरचनाएं हैं और एक निरंतर समय में व्यक्ति रिकॉर्ड प्राप्त और सेट करता है। यह निश्चित रूप से जाने का रास्ता है।

एक चीज जो विकल्प # 3 की कमी है, वह एक स्थिर नियतांक क्रमबद्धता है (जो विकल्प # 2 के ऊपर है)। यदि आपको इसकी आवश्यकता है, तो मैं व्यक्ति आईडी के क्रमबद्ध सरणी को एक अलग संरचना के रूप में रखने की सलाह दूंगा जब आपको व्यक्तियों को क्रम में सूचीबद्ध करने की आवश्यकता हो। इसका फायदा यह होगा कि आप एक ही डेटा सेट के अलग-अलग ऑर्डर के लिए कई ऐसे एरेज़ रख सकते हैं।


0

आपके अवरोध को देखते हुए कि आपके पास केवल मूल्य के रूप में नाम होगा, मैं पहला विकल्प चुनूंगा। यह सबसे साफ है, कम से कम ओवरहेड और सबसे तेज़ दिख रहा है।

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