क्या मेरा अनुक्रमिक संग्रह इंडेक्स 0 या इंडेक्स 1 पर शुरू होना चाहिए?


25

मैं एक डिवाइस के लिए एक ऑब्जेक्ट मॉडल बना रहा हूं जिसमें कई चैनल हैं। ग्राहक और मैं के बीच उपयोग की जाने वाली संज्ञा Channelऔर हैं ChannelSet। ("सेट" शब्दार्थिक रूप से सटीक नहीं है, क्योंकि यह आदेश दिया गया है और एक उचित सेट नहीं है। लेकिन यह एक अलग समय के लिए एक समस्या है।)

मैं C # का उपयोग कर रहा हूं। यहाँ एक उपयोग उदाहरण है ChannelSet:

// load a 5-channel ChannelSet
ChannelSet channels = ChannelSetFactory.FromFile("some_5_channel_set.json");

Console.Write(channels.Count);
// -> 5

foreach (Channel channel in channels) {
    Console.Write(channel.Average);
    Console.Write(",  ");
}
// -> 0.3,  0.3,  0.9,  0.1,  0.2

सभी बांका है। हालांकि, क्लाइंट प्रोग्रामर नहीं हैं और वे बिल्कुल शून्य अनुक्रमित होने से भ्रमित होंगे - पहला चैनल उनके लिए चैनल 1 है। लेकिन, सी # के साथ संगतता के लिए, मैं ChannelSetशून्य से अनुक्रमित रखना चाहता हूं

जब वे बातचीत करते हैं तो मेरी देव टीम और क्लाइंट्स के बीच कुछ डिस्कशन होना निश्चित है। लेकिन इससे भी बदतर, कोडबेस के भीतर इसे कैसे संभाला जाता है, इस बारे में कोई असंगतता एक संभावित समस्या है। उदाहरण के लिए, यहां एक UI स्क्रीन है जहां अंतिम उपयोगकर्ता ( जो 1 अनुक्रमण के संदर्भ में सोचता है ) चैनल 13 का संपादन कर रहा है:

चैनल १३ या १२?

वह Saveबटन अंततः कुछ कोड में परिणाम करने वाला है। यदि ChannelSet1 अनुक्रमित है:

channels.GetChannel(13).SomeProperty = newValue;  // notice: 13

या यदि यह शून्य अनुक्रमित है:

channels.GetChannel(12).SomeProperty = newValue;  // notice: 12

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

तो, क्या इस तरह का निर्णय आपको कभी काट सकता है? क्या मुझे शून्य सूचकांक या एक सूचकांक चाहिए?


60
"क्या सरणी सूचकांकों की शुरुआत 0 या 1 से होनी चाहिए? 0.5 का मेरा समझौता बिना खारिज कर दिया गया, मुझे लगा, उचित विचार है।" - स्टेन केली-बूटल
gnat

2
@gnat यह एक अच्छी बात है कि मैं कार्यालय में अकेला हूँ - कंप्यूटर स्क्रीन पर हँसी के फूटने से आमतौर पर उत्पादकता के अच्छे संकेतक नहीं होते हैं!
kdbanman

4
क्या चैनलों को सेट में अपनी स्थिति से पहचाना जाना चाहिए? क्या आप उन्हें इसके बजाय किसी और चीज़ से पहचान नहीं सकते हैं (जैसे कि आवृत्ति अगर टीवी चैनल थे)?
svick

@svick, यह एक शानदार बिंदु है। मैं बाद में विभिन्न पहचानकर्ताओं द्वारा चैनल एक्सेस की अनुमति दे सकता हूं, लेकिन ग्राहकों के प्राथमिक लिंगो को वास्तव में एक अनुक्रमित चैनल नंबर लगता है।
kdbanman

एक त्वरित रीड से ऐसा लगता है कि दक्षता के मामले के रूप में सूचकांकों का उपयोग करने की कोई आवश्यकता नहीं है, इसलिए आप सरणियों के बारे में सोचने की आवश्यकता के बिना चैनल आईडी और चैनलों को सीधे लिंक करने के लिए कुछ प्रकार के मानचित्र का उपयोग कर सकते हैं। मुझे लगता है कि यह वही है जो रॉब में हो रहा है, और अगर आप सूचकांकों का उपयोग करने का विकल्प चुनते हैं, तो मैं उनके समाधान से भी सहमत हूं।
मैथ्यू पढ़ें

जवाबों:


24

ऐसा लगता है कि आप पहचानकर्ता Channelको अपनी स्थिति के भीतर के लिए भ्रमित कर रहे हैं ChannelSet। निम्नलिखित मेरा विज़ुअलाइज़ेशन है कि आपका कोड / टिप्पणी इस समय कैसी दिखेगी:

public sealed class ChannelSet
{
    private Channel[] channels;
    /// <summary>Retrieves the specified channel</summary>
    /// <param name="channelId">The id of the channel to return</param>
    Channel GetChannel(int channelId)
    {
        return channels[channelId-1];
    }
}

ऐसा महसूस होता है कि आपने तय कर लिया है कि क्योंकि संख्याओं के Channelभीतर एक ChannelSetकी पहचान की गई है जिनकी ऊपरी और निचली सीमा है, उन्हें अनुक्रमित होना चाहिए और इसलिए यह C #, 0 आधारित है। यदि प्रत्येक चैनल को संदर्भित करने का प्राकृतिक तरीका 1 और X के बीच की संख्या से है, तो उन्हें 1 और X के बीच की संख्या से संदर्भित करें। कोशिश न करें और उन्हें अनुक्रमित होने के लिए बाध्य करें।

यदि आप वास्तव में उन्हें 0 आधारित सूचकांक द्वारा एक्सेस करने का एक तरीका प्रदान करना चाहते हैं (इससे आपके अंतिम उपयोगकर्ता को क्या लाभ मिलता है, या डेवलपर्स कोड का उपभोग करते हैं?) तो एक अनुक्रमणिका लागू करें :

public sealed class ChannelSet
{
    private Channel[] channels;
    /// <summary>Retrieves the specified channel</summary>
    /// <param name="channelId">The id of the channel to return</param>
    public Channel GetChannel(int channelId)
    {
        return channels[channelId-1];
    }

    /// <summary>Return the channel at the specified index</summary>
    public Channel this[int index]
    {
        return channels[index];
    }
}

2
यह वास्तव में पूर्ण और संक्षिप्त उत्तर है। यह बिल्कुल वही दृष्टिकोण है जो मैंने दूसरे उत्तरों से प्राप्त किया है।
kdbanman

7
राहगीरों, मैंने इस उत्तर को स्वीकार कर लिया है, लेकिन यह धागा अच्छे उत्तरों से भरा है, इसलिए आगे पढ़ें।
kdbanman

बहुत अच्छा, @Rob। "मुझे पता है कि इंडेक्सर्स का उपयोग कैसे करना है।" - नव
जेसन पी सल्लिंगर

35

सूचकांक 1 के साथ यूआई दिखाएं, कोड में इंडेक्स 0 का उपयोग करें।

उस ने कहा, मैंने इस तरह के ऑडियो उपकरणों के साथ काम किया और चैनलों के लिए इंडेक्स 1 का इस्तेमाल किया और निराशा से बचने में मदद करने के लिए कोड को कभी "इंडेक्स" या इंडेक्सर्स का उपयोग नहीं किया। कुछ प्रोग्रामर ने फिर भी शिकायत की, इसलिए हमने इसे बदल दिया। फिर अन्य प्रोग्रामर्स ने शिकायत की।

बस एक उठाओ और इसके साथ रहो। दरवाजे से सॉफ्टवेयर निकलने की भव्य योजना में हल करने के लिए बड़ी समस्याएं हैं।


12
इसका अपवाद: यदि आप 1-आधारित भाषा का उपयोग कर रहे हैं। आपका कोड आपके बाकी कोड और आपकी भाषा के अनुरूप होना चाहिए, इसलिए 0 # C- आधारित, VBA (!) या Lua में 1-आधारित है। आपका यूआई ऐसा होना चाहिए जो मनुष्य अपेक्षा करता है (जो लगभग हमेशा 1-आधारित है)।
user253751

1
@ मिनीबिस - अच्छी बात है, मैंने ऐसा नहीं सोचा था।
तेलेस्टीन

3
एक चीज जो मुझे कभी-कभी पुराने दिनों की प्रोग्रामिंग के बारे में याद आती है, वह है BASIC "OPTION BASE" ...
ब्रायन नोब्लाच

1
@ BlueRaja-DannyPflughoeft: जबकि मुझे हमेशा लगता Option Baseथा कि मूर्खतापूर्ण है, मुझे यह सुविधा पसंद आई कि कुछ भाषाओं ने सरणियों को व्यक्तिगत रूप से मनमाने ढंग से कम सीमा निर्दिष्ट करने की अनुमति दी। यदि किसी के पास वर्ष के हिसाब से डेटा है, तो उदाहरण के लिए, एक एरे से जुड़े एरे [firstYear..lastYear]को हमेशा के लिए एलिमेंट एक्सेस करने से बेहतर माना जा सकता है [thisYear-firstYear]
सुपरकैट

1
@ BlueRaja-DannyPflughoeft एक आदमी की बग एक और आदमी की विशेषता है ...
ब्रायन नोब्लुक

21

दोनों का उपयोग करें।

अपने कोर कोड के साथ यूआई को न मिलाएं। आंतरिक रूप से (एक पुस्तकालय के रूप में) आपको "बिना यह जाने" कोड करना चाहिए कि सरणी के प्रत्येक तत्व को अंतिम उपयोगकर्ता द्वारा कैसे बुलाया जाएगा। "प्राकृतिक" 0-अनुक्रमित सरणियों और संग्रह का उपयोग करें।

प्रोग्राम का वह हिस्सा जो यूआई के साथ डेटा को जोड़ता है, दृश्य, उपयोगकर्ता के मानसिक मॉडल और वास्तविक कार्य करने वाले 'लाइब्रेरी' के बीच डेटा का सही अनुवाद करने के लिए ध्यान रखना चाहिए।

यह बेहतर क्यों है?

  • कोड क्लीनर हो सकता है, इंडेक्सिंग का अनुवाद करने के लिए कोई हैक नहीं। यह प्रोग्रामर को अप्राकृतिक सम्मेलनों का उपयोग करने के लिए उनका अनुसरण करने और याद रखने की उम्मीद न करके भी मदद करता है।
  • उपयोगकर्ता उन अनुक्रमणों का उपयोग करेंगे, जिनकी वे अपेक्षा करते हैं। आप उन्हें नाराज नहीं करना चाहते।

12

आप दो अलग-अलग कोणों से संग्रह देख सकते हैं।

(1) यह पहली जगह है, एक नियमित अनुक्रमिक संग्रह , एक सरणी या सूची की तरह। 0अधिवेशन के बाद सूचकांक स्पष्ट रूप से सही समाधान है। आप सूचकांकों के लिए पर्याप्त प्रविष्टियाँ और मानचित्र चैनल संख्या आवंटित करते हैं, जो तुच्छ है (बस घटाना 1)।

(२) आप संग्रह अनिवार्य रूप से चैनल पहचानकर्ता और चैनल जानकारी ऑब्जेक्ट के बीच मैपिंग है । यह सिर्फ इतना होता है कि चैनल पहचानकर्ता पूर्णांकों की एक अनुक्रमिक सीमा है; कल ऐसा कुछ हो सकता है [1, 2, 3, 3a, 4, 4.1, 6, 8, 13]। आप इस आदेशित सेट का उपयोग मैपिंग कुंजियों के रूप में करते हैं।

दृष्टिकोणों में से एक चुनें, इसे दस्तावेज करें, और इसे छड़ी करें। लचीलेपन के दृष्टिकोण से, मैं (2) के साथ जाऊंगा, क्योंकि चैनल नंबर (कम से कम प्रदर्शित नाम) का प्रतिनिधित्व भविष्य में बदलने की संभावना है।


मैं वास्तव में आपके उत्तर के भाग 2 की सराहना करता हूं। मुझे लगता है कि मैं ऐसा कुछ अपनाऊंगा। सूचकांक एक्सेसर ( channels[int]) हो जाएगा शून्य अनुक्रमित पूर्णांकों, और प्राप्त करें accessors GetChannelByFrequency, GetChannelByName, GetChannelByNumberलचीला हो जाएगा।
kdbanman

1
दूसरा दृष्टिकोण निश्चित रूप से सबसे अच्छा है। मेरे स्थानीय ब्रॉडकास्टर LCNs के साथ 1 से 201 तक 32 चैनल पेश करते हैं । इसके लिए एक विरल सरणी (84% खाली) की आवश्यकता होगी। यह वैचारिक रूप से टेलीफोन नंबर द्वारा अनुक्रमित सरणी में लोगों के संग्रह को संग्रहीत करने जैसा है।
केली थॉमस

3
इसके अलावा, किसी भी संग्रह इतना छोटा है कि यह एक यूआई लटकती का प्रतिनिधित्व करती है अत्यंत डेटा संरचना के रूप में एक सरणी के विशिष्ट प्रदर्शन विशेषताओं से लाभ होने की संभावना नहीं है। तो उपयोगकर्ता द्वारा "चैनल 1" नामक चीज को कोड में भी "1" कहा जा सकता है, और Dictionaryया का उपयोग कर सकता है SortedDictionary
स्टीव जेसोप

1
कम से कम आश्चर्य का सिद्धांत यह होगा कि operator [] (int index)0-आधारित होना चाहिए, जबकि operator [] (IOrdered index)ऐसा नहीं होगा। (अनुमानित वाक्यविन्यास के लिए क्षमायाचना, मेरा C # बहुत कठोर है।)
9000

2
@kdbanman: व्यक्तिगत रूप से, मैं यह तर्क दूंगा कि जैसे ही आप []एक ऐसी भाषा में ओवरलोडिंग कर रहे हैं जो इस कुंजी को मनमाने ढंग से कुंजी द्वारा देखने के लिए उपयोग करता है, तो प्रोग्रामर को यह नहीं मानना ​​चाहिए कि चाबियाँ शुरू से ही हैं 0और सन्निहित हैं, और उस आदत को तेज करना चाहिए। वे शुरू कर सकते हैं 0, या 1, या 1000, या स्ट्रिंग "Channel1", यह []मनमाने ढंग से कुंजी के साथ ऑपरेटर का उपयोग करने का पूरा बिंदु है । OTOH, अगर यह C था और कोई कह रहा था "क्या मुझे 0शुरू करने के लिए अप्रयुक्त एक तत्व में तत्व छोड़ना चाहिए 1" तो मैं "स्पष्ट रूप से, हाँ" नहीं कहूंगा, यह एक करीबी कॉल होगा, लेकिन मैं इसके लिए झुकूंगा "नहीं"।
स्टीव जेसोप

3

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

अब आप एक यूजर इंटरफेस में क्या प्रदर्शित करते हैं, यह पूरी तरह से आपके और आपके ग्राहक के लिए है। बस चैनल नंबर के रूप में i + 1 को चैनल नंबर के साथ प्रदर्शित करें, अगर यह आपके क्लाइंट को खुश करता है।

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

आप UI और कोड के बीच रूपांतरण के बारे में चिंता करने लगते हैं। यदि वह आपको चिंतित करता है, तो चैनल नंबर के उपयोगकर्ता इंटरफ़ेस प्रतिनिधित्व को ले जाने वाला एक वर्ग बनाएं। यूआई प्रतिनिधित्व "चैनल 13" में 12 नंबर को कॉल करने वाली एक कॉल, और एक कॉल नंबर 12 में "चैनल 13" को बदल देती है। आपको ऐसा करना चाहिए, वैसे भी ग्राहक द्वारा अपना मन बदलने पर, इसलिए कोड की सिर्फ दो लाइनें हैं बदलने के लिए। और यह काम करता है अगर ग्राहक रोमन अंक, या पत्र ए से जेड के लिए पूछता है।


1
मैं आपके उत्तर को सत्यापित नहीं कर सकता क्योंकि मेरा कुत्ता मुझे नहीं बताएगा कि वह किस प्रकार के इंडेक्स का उपयोग करता है।
अरमानी

3

आप दो अवधारणाओं को मिला रहे हैं: अनुक्रमण और पहचान। वे एक ही चीज नहीं हैं और भ्रमित नहीं होना चाहिए।

इंडेक्सिंग का उद्देश्य क्या है? तेजी से यादृच्छिक पहुँच। यदि प्रदर्शन कोई समस्या नहीं है, और अपना विवरण दिया है, तो यह एक संग्रह का उपयोग करना, जो एक सूचकांक है अनावश्यक और संभवतः आकस्मिक है।

यदि आप (या आपकी टीम) सूचकांक बनाम पहचान से भ्रमित हो रहे हैं, तो आप सूचकांक नहीं होने से उस समस्या को हल कर सकते हैं। एक शब्दकोश या एक enumerable या तो का उपयोग करें और मूल्य से चैनल प्राप्त करें।

channels.First(c=> c.Number == identity).SomeProperty = newValue;
channels[identity].SomeProperty = newValue;

पहला अधिक स्पष्ट है, दूसरा छोटा है - वे एक ही आईएल में अनुवाद नहीं कर सकते हैं या नहीं कर सकते हैं, लेकिन किसी भी तरह से, आप इसे ड्रॉपडाउन के लिए उपयोग कर रहे हैं, यह काफी तेज होना चाहिए।


2

आप अपनी ChannelSetकक्षा के माध्यम से एक ऐसे इंटरफ़ेस को उजागर कर रहे हैं, जिसके बारे में आप अपने उपयोगकर्ताओं से बातचीत करने की उम्मीद करते हैं। मैं इसे जितना संभव हो उतना स्वाभाविक रूप से उपयोग करने के लिए बनाऊंगा। यदि आप उम्मीद करते हैं कि आपके उपयोगकर्ता 0 के बजाय 1 से गणना शुरू करेंगे, तो इस वर्ग और इसके उपयोग को उस अपेक्षा को ध्यान में रखते हुए उजागर करें।


1
उसमें समस्या है! मेरे अंतिम उपयोगकर्ता 1 से शुरू होने की उम्मीद कर रहे हैं, और मेरे देव उपयोगकर्ता (स्वयं शामिल हैं) 0. से शुरू होने की उम्मीद कर रहे हैं
kdbanman

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

2

0-आधारित अनुक्रमण लोकप्रिय था, और महत्वपूर्ण लोगों द्वारा बचाव किया गया था, क्योंकि घोषणा वस्तु के आकार को दर्शाती है।

आधुनिक कंप्यूटरों के साथ, उन कंप्यूटरों के साथ जिनका आपके उपयोगकर्ता उपयोग कर रहे हैं, क्या ऑब्जेक्ट का आकार बिल्कुल महत्वपूर्ण है?

यदि आपका लैंगगॉव (C #) किसी सरणी के पहले और अंतिम तत्व को घोषित करने के एक साफ तरीके का समर्थन नहीं करता है, तो आप तार्किक शुरुआत और अंत की पहचान करने के लिए घोषित सरणी (या डायनामिक चर) का उपयोग कर सकते हैं। सरणी का सक्रिय क्षेत्र।

UI ऑब्जेक्ट्स के लिए, आप निश्चित रूप से अपनी मैपिंग के लिए एक डिक्शनरी ऑब्जेक्ट का उपयोग कर सकते हैं, (यदि आपको 10 मिलियन ऑब्जेक्ट मिल गए हैं, तो आपको UI प्रॉब्लम हो सकती है), और यदि बेस्ट डिक्शनरी ऑब्जेक्ट एक सूची के साथ निकला है। या तो अंत में बर्बाद हुआ स्थान, आपने कुछ भी महत्वपूर्ण नहीं खोया है।


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

@phyrfox: शून्य-आधारित अनुक्रमण के लिए मैं जो अमूर्तता पसंद करता हूं, वह यह है कि अनुक्रमणिका वस्तुओं के बीच की स्थिति को पहचानती है ; पहली वस्तु सूचकांक 0 और 1 के बीच है, दूसरा 1 और 2 के बीच है, आदि को देखते हुए x <= y <= z, पर्वतमाला [x, y] और [y, z] लगातार होगा लेकिन ओवरलैप नहीं होगा, और या तो दोनों कोई विशेष कोने के मामलों की आवश्यकता के साथ खाली हो सकते हैं। शून्य-आधारित अनुक्रमण के साथ "आइटम के बीच बैठते हैं" मॉडल को अपनाने पर, छह वस्तुओं की एक सूची 0 से 6 तक की सीमा होती है; एक-आधारित अनुक्रमण के साथ यह 1 से 7 तक बैठेगा। ध्यान दें कि यह अमूर्त "वन-परे" संकेत के साथ अच्छी तरह से फिट बैठता है।
सुपरकाट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.