2009-08-31 18 views
5

मैं वर्तमान में एक प्रोग्राम बनाने की कोशिश कर रहा हूं जो संकेत शक्ति के आधार पर स्थान का अनुमान लगाता है। संकेत शक्ति मान एक int है और फिर मुझे श्रेणियों के साथ एक लुकअप शब्दकोश की आवश्यकता है।सी # शब्दकोश को देखो

तो मैं की तरह कुछ होगा:

Signal Strenth    Position 
0-9       1 
10-19       2 
20-29       3 

और फिर मैं देखने के लिए क्या स्थिति एक सिग्नल की शक्ति के लिए, उदाहरण के लिए 15 स्थान देने के लिए 2.

मैं मैं जानता हूँ कि संबंधित हैं संबंधित चाहेगा क्या सिर्फ बयानों का भार हो सकता है लेकिन क्या किसी प्रकार के लुकअप डिक्शनरी का उपयोग करके ऐसा करने का कोई अच्छा तरीका है?

उत्तर

11

आप मनमाने ढंग से लेकिन लगातार पर्वतमाला है, तो आप ऊपरी सीमा की एक सरणी का उपयोग करें और स्थिति प्राप्त करने के लिए एक द्विआधारी खोज प्रदर्शन कर सकते हैं:

// Definition of ranges 
int[] ranges = new int[] { 9, 19, 29 }; 

// Lookup 
int position = Array.BinarySearch(ranges, 15); 
if (position < 0) 
    position = ~position; 

// Definition of range names 
string[] names = new string[] { "home", "street", "city", "far away" }; 

Console.WriteLine("Position is: {0}", names[position]); 

Array.BinarySearch यदि यह अस्तित्व में है तो सरणी में आइटम की अनुक्रमणिका लौटाती है (सरणी को स्पष्ट रूप से सॉर्ट किया जाना चाहिए) या बिटवाई उलटा इंडेक्स जहां सरणी को सॉर्ट करने के लिए आइटम डाला जाना चाहिए।

+0

अधिक स्पष्टीकरण यह एक आदर्श उत्तर देगा। –

+1

अच्छा जवाब। मनमानी श्रेणियों के किसी भी सेट के साथ काम करेगा जिसमें उनके बीच कोई अंतराल नहीं है। – jrista

+0

धन्यवाद, क्या इस तरह के कुछ का उपयोग करना संभव है यदि पदों का नाम सिर्फ एक संख्या से बढ़ता है जो एक से बढ़ता है? – DNN

11

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

int position = signalStrength/10 + 1; 

दया,

दान

+2

उत्कृष्ट उत्तर, मानते हैं कि श्रेणियां वास्तव में 10 के समूहों में हैं और यह केवल एक नमूना विसंगति नहीं थी। –

+0

जैसे ही शक्ति अधिक हो जाती है, वे हमेशा 10 के दशक में नहीं रहेंगे। मुझे जवाब पसंद है हालांकि – DNN

0

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

कुछ की तरह:

Dictionary<int, int> values; 

values = new Dictionary<int, int>(); 

values[0] = 1; 
values[1] = 1; 
... 
values[29] = 3; 

और उसके बाद, यह उपयोग करने के लिए:

Console.WriteLine(values[27].ToString()); 
-1

जेनरिक उपयोग करके देखें:

Dictionary<int,int> lookup = new Dictionary<int,int>(); 
lookup.Add(0,1); 
lookup.Add(1,1); 
lookup.Add(2,1); 
lookup.Add(3,1); 
... 
lookup.Add(9,1); 
lookup.Add(10,2); 
lookup.Add(11,2); 

आदि

फिर, देखने [22] 3. मैं मूल्य का मूल्य वापस करूँगा अपनी 'रेंज' बनाने के लिए लूप के सेट का उपयोग करके घोंसला। इस विधि के साथ, आपको ओ (1) एक्सेस समय की गारंटी है।

+1

क्या आप गंभीरता से सुझाव दे रहे हैं कि वह अपनी श्रेणियों में प्रत्येक अभिन्न मूल्य के लिए शब्दकोश में अलग-अलग मान जोड़ता है? –

+0

हां। छोटी संख्या में श्रेणियों के लिए, यह ओपी की तलाश में हो सकता है। क्या आपके पास एक बेहतर समाधान है? यदि हां, तो पोस्ट करें। –

+0

@Charlie: मुझे पहले से ही डीटीबी और agileguy द्वारा सबमिट किए गए उत्तरों को गूंजने की कोई ज़रूरत नहीं है। –

0

भविष्य के विस्तार के लिए मैं 2 शब्दकोश करूंगा। शायद ज़रुरत पड़े उन दरों में परिवर्तन तो एक

dictionary<string,dictionary<int,int>> 

या सिर्फ कस्टम कक्षाओं का उपयोग स्ट्रिंग कम मेड, अपने foreach में पर्वतमाला प्रारंभिक मान initilixing उच्च है, तो आप बदल सकते हैं की तरह स्थिर तार होगा

1

अच्छा उद्देश्य का एक कार्य है। उपरोक्त सभी समाधान अच्छी तरह से मानते हैं कि किसी दिए गए रेंज में पूर्णांक की एक छोटी संख्या है। अन्यथा आप अपने समूह को निर्धारित करने के लिए असली दुनिया गणित कार्य का उपयोग करना चाह सकते हैं। उदाहरण के लिए, दिए गए उदाहरण के लिए, आपका उत्तर फ़ंक्शन x% 10 + 1 होगा; वह एक शब्दकोश से बहुत तेज दौड़ जाएगा।

0

एक समाधान एक साधारण सूची का उपयोग करना होगा, जहां सूची में प्रत्येक स्थिति एक अलग स्थिति का प्रतिनिधित्व करती है जिसके लिए आप स्कैनिंग कर रहे हैं। कोड में, यह ऐसा कुछ दिखाई दे सकता है (यह मानते हुए कि सभी स्थिति संख्या अनुक्रमिक हैं):

** नोट: मैंने वास्तव में यह कोड यह सुनिश्चित करने के लिए नहीं चला है कि यह काम करता है ... आपको भी आवश्यकता हो सकती है IndexOf ऑपरेशन के लिए आदेश उचित स्थिति वापस जाने के लिए में Range पर एक IEqualityComparer लागू:

public class Range 
{ 
    public Range(int min, int max) 
    { 
     this.Min = min; 
     this.Max = max; 
    } 

    public int Min 
    { 
     get; 
     private set; 
    } 

    public int Max 
    { 
     get; 
     private set; 
    } 
}
:

public class Controller 
{ 
    List m_positions = new List(); 

    public void LoadPositions() 
    { 
     m_positions.Add(new Range(0, 9)); 
     m_positions.Add(new Range(10, 19)); 
     m_positions.Add(new Range(20, 29)); 
    } 

    public int GetPosition (int signal) 
    { 
     Range range = m_positions.Single(a => IsBetween(signal, a.Min, a.Max)); 

     return m_positions.IndexOf(range); 
    } 

    private static bool IsBetween (int target, int min, int max) 
    { 
     return min = target; 
    } 
}

यह शायद बहुत आत्म व्याख्यात्मक है, लेकिन किसी भी भ्रम से बचने के लिए, यहाँ क्या Range वर्ग नज़र आ सकते हैं

0

यदि सिग्नल रेंज और स्थिति के बीच सीधा सहसंबंध है तो @agileguy का सुझाव दिया गया है।

आप पदों रैखिक वितरित किए गए हों सिग्नल की शक्ति भर में गैर तो एक ही रास्ता होगा:

class SignalStrengthPositionMapper 
{ 
    private static readonly int[] signalStrength = { Int32.MinValue, 0, 5, 11, 15, 20, 27, 35 }; 
    public static int GetPosition(int strength) 
    { 
     return StrengthSearch(0, signalStrength.Length, strength); 
    } 

    // modified binary search 
    private static int StrengthSearch(int start, int end, int strength) 
    { 
     int mid = 0; 
     while (start <= end) 
     { 
      mid = (start + end)/2; 

      if (strength >= signalStrength[mid])   // lower bound check 
      { 
       start = mid + 1; 
       if (strength < signalStrength[start]) // upper bound check 
        return mid; 
      } 
      else if (strength < signalStrength[mid])  // upper bound check 
      { 
       end = mid - 1; 
       if (strength >= signalStrength[end])  // lower bound check 
        return mid; 
      } 
     } 
     return 0; 
    } 
} 
2

आप शब्दकोश का उपयोग करना चाहते हैं, तो आप कम से कम पर्वतमाला से निपटने के लिए कुछ विशेष कुंजी प्रकार की जरूरत है। कीटाइप सार और दो व्युत्पन्न प्रकार KeyTypeRange (int int) और KEyTypeSearch (int) हो सकता है। KeyTypeRange के साथ KeyTypeSearch की तुलना करने के लिए कुछ विशेष तुलना तर्क लागू किए जाने चाहिए।

SortedDictionary<KeyType,int> lookup = new Dictionary<int,int>(); 
lookup.Add(new KeyTypeRange(1,10),1); 
lookup.Add(new KeyTypeRange(11,20),2); 
lookup.Add(new KeyTypeRange(21,30),3); 
lookup.TryGetValue(new KeyTypeSearch(15)); 

यह विभिन्न खोज कुंजी और शब्दकोशों में महत्वपूर्ण मानों का उपयोग करने के लिए एक संभावित समाधान दिखाता है। लेकिन यह इस समस्या के लिए ओवरकिल लगता है। बाइनरीशर्च समाधान द्वारा इस समस्या को हल किया जाता है।

+0

इस दृष्टिकोण का जिक्र करने के लिए अच्छा है। मैं बाइनरी खोज पसंद करता हूं लेकिन पहले उल्लेख किए गए सभी संभावित मानों के साथ एक शब्दकोश लोड करने के बजाय एक KeyTypeRange का उपयोग करना इंगित करना अच्छा होता है। – Steve

+0

@ थॉमस: दिलचस्प लगता है। क्या आप अपना विचार विस्तृत कर सकते हैं? 'शब्दकोश 'हैश तालिका के रूप में लागू किया गया है। आप 'KeyTypeRange' और' KeyTypeSearch' के 'GetHashCode' को कैसे कार्यान्वित करते हैं, जैसे कि' नई की टाइप खोज (15) 'नई कुंजी टाइप प्रकार (1,10)' उत्पन्न करती है? – dtb

+0

वास्तव में आप शब्दकोश का उपयोग नहीं कर सकते हैं, आपको SortedDictionary का उपयोग करना चाहिए, क्योंकि इस समस्या के लिए हैश फ़ंक्शन प्रदान करना संभव नहीं है। SortedDictionary कुंजी की तुलना int IComparer द्वारा की जाती है। कॉम्पैयर (टी एक्स, टी वाई) जो कार्यान्वित करना आसान है। –

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