2009-08-31 46 views
5

Tôi hiện đang cố gắng tạo một chương trình ước tính vị trí dựa trên cường độ tín hiệu. Giá trị cường độ tín hiệu là một int và sau đó tôi cần một từ điển tra cứu với các dãy.C# Tra cứu từ điển

Vì vậy, tôi sẽ có một cái gì đó như:

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

và sau đó tôi sẽ muốn tìm kiếm những gì vị trí của một cường độ tín hiệu liên quan đến, ví dụ 15 sẽ liên quan đến vị trí 2.

Tôi biết tôi chỉ có thể có tải trọng của các câu lệnh if nhưng có cách nào tốt để làm điều này bằng cách sử dụng một số loại từ điển tra cứu?

Trả lời

11

Nếu bạn có phạm vi tùy ý nhưng liên tiếp, bạn có thể sử dụng một loạt các giới hạn trên và thực hiện tìm kiếm nhị phân để có được vị trí:

// 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 trả về chỉ mục của mục trong mảng nếu nó tồn tại (mảng phải được sắp xếp rõ ràng) hoặc chỉ mục đảo ngược bit, nơi mục sẽ được chèn vào để giữ cho mảng được sắp xếp.

+0

Giải thích thêm sẽ làm cho điều này trở thành một câu trả lời lý tưởng. –

+1

Câu trả lời hay. Sẽ làm việc với bất kỳ tập hợp các phạm vi tùy ý nào không có khoảng trống giữa chúng. – jrista

+0

Cảm ơn, Có thể sử dụng một cái gì đó tương tự như thế này nếu các vị trí được đặt tên thay vì chỉ là một con số tăng lên một không? – DNN

11

gì về:

int position = signalStrength/10 + 1; 

Kindness,

Dan

+2

Câu trả lời xuất sắc, giả sử các phạm vi thực sự nằm trong nhóm 10 và không chỉ là một mẫu bất thường. –

+0

Khi sức mạnh tăng lên, chúng sẽ không luôn ở độ tuổi 10. Tôi thích câu trả lời mặc dù – DNN

0

Bạn có thể làm một từ điển, nơi int Đầu tiên là cường độ tín hiệu và int thứ hai là vị trí này. Bạn sẽ cần phải thêm một mục nhập cho mỗi giá trị trong phạm vi (vì vậy, một cho cường độ tín hiệu 0, vị trí 1, cường độ tín hiệu 1, vị trí 1, v.v.), nhưng nó sẽ là một tra cứu một dòng rất nhanh.

Cái gì như:

Dictionary<int, int> values; 

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

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

và sau đó, để truy cập vào nó:

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

Hãy thử sử dụng Generics:

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); 

vv

Sau đó, tra cứu [22] sẽ trả về giá trị của 3. Tôi sug cử chỉ bằng cách sử dụng một tập hợp các vòng để tạo 'dải ô' của bạn. Với phương pháp này, bạn được đảm bảo thời gian truy cập O (1).

+1

Bạn có nghiêm túc gợi ý rằng anh ta thêm các giá trị riêng biệt vào Từ điển cho mọi giá trị tích phân trong phạm vi của anh ấy không? –

+0

Có. Đối với một số ít phạm vi, nó có thể là những gì OP đang tìm kiếm. Bạn có giải pháp tốt hơn không? Nếu có, hãy đăng. –

+0

@Charlie: Không cần tôi trả lời các câu trả lời đã được gửi bởi dtb và agileguy. –

0

Để mở rộng trong tương lai, tôi sẽ thực hiện 2 từ điển. Chỉ trong trường hợp những giá thay đổi do đó, một

dictionary<string,dictionary<int,int>> 

hoặc chỉ sử dụng các lớp tùy chỉnh chuỗi sẽ là chuỗi tĩnh như thấp med, cao, sau đó bạn có thể thay đổi các dãy trong foreach bạn initilixing các giá trị ban đầu

1

Tốt là chức năng của mục đích. Tất cả các giải pháp trên làm việc tốt giả định rằng bất kỳ phạm vi nhất định là một số lượng nhỏ các số nguyên. Nếu không, bạn có thể muốn sử dụng bất kỳ chức năng toán học thực tế nào để xác định nhóm của bạn. Ví dụ, đối với ví dụ được đưa ra, hàm trả lời của bạn sẽ là x% 10 + 1; Điều đó sẽ chạy nhanh hơn nhiều so với từ điển.

0

Một giải pháp là sử dụng danh sách đơn giản, trong đó mỗi vị trí trong danh sách thể hiện một vị trí khác mà bạn đang quét tìm. Trong mã, nó có thể trông giống như thế này (giả định rằng tất cả các số vị trí là tuần tự):

** Lưu ý: Tôi chưa thực sự chạy mã này để đảm bảo nó hoạt động như ... bạn cũng có thể cần thực hiện một IEqualityComparer trên Range để các hoạt động IndexOf để trả lại vị trí thích hợp:

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; 
    } 
}

đây có thể là khá tự giải thích, nhưng để tránh bất kỳ sự nhầm lẫn, đây là những gì lớp Range có thể trông giống như:

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; 
    } 
}
0

nếu có sự tương quan trực tiếp giữa dải tín hiệu và vị trí thì hãy sử dụng những gì @agileguy đề xuất.

Nếu bạn đã vị trí phân phối phi tuyến tính trên cường độ tín hiệu sau đó một trong những cách sẽ là:

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

Khi bạn muốn sử dụng từ điển, bạn cần ít nhất một số loại chìa khóa đặc biệt để đối phó với những dãy. KeyType có thể được trừu tượng và hai loại có nguồn gốc KeyTypeRange (int int) và KEyTypeSearch (int). Một số logic so sánh đặc biệt phải được triển khai để so sánh KeyTypeSearch với KeyTypeRange.

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)); 

Nó hiển thị giải pháp khả thi để sử dụng các khóa tìm kiếm và giá trị khóa khác nhau trong từ điển. Nhưng điều này có vẻ là quá mức cần thiết cho vấn đề này. Vấn đề này được giải quyết tốt nhất bởi giải pháp BinarySearch.

+0

Tốt để đề cập đến phương pháp này. Tôi thích tìm kiếm nhị phân nhưng tốt hơn nên chỉ ra bằng cách sử dụng một KeyTypeRange thay vì tải một từ điển với tất cả các giá trị có thể như đã được đề cập trước đó. – Steve

+0

@Thomas: Âm thanh thú vị. Bạn có thể xây dựng ý tưởng của mình không? 'Từ điển ' được triển khai dưới dạng bảng băm. Làm thế nào để bạn thực hiện 'GetHashCode' của' KeyTypeRange' và 'KeyTypeSearch' sao cho' new KeyTypeSearch (15) 'tạo ra' new KeyTypeRange (1,10) '? – dtb

+0

Trong thực tế, bạn không thể sử dụng từ điển , bạn phải sử dụng SortedDictionary , vì không thể cung cấp hàm băm cho vấn đề này. Các phím SortedDictionary được so sánh bằng int IComparer .Compare (T x, T y) rất dễ thực hiện. –

Các vấn đề liên quan