2010-07-15 17 views
1

我所擁有的是用戶輸入字符串的文本框。字符串將如下所示: G32:04:20:40將文本文件中的搜索結果排序到列表框中

然後用戶點擊搜索按鈕。然後程序必須打開一個文本文件並搜索「最近」的五個字符串,並將它們顯示在列表框中。

我會盡可能地定義「最接近的字符串」(很可能使用非常長的複雜示例)。

包含在文本文件中的數據是這樣的:

G32:63:58:11 JG01 
G32:86:98:30 JG01 
G33:50:05:11 JG06 
G33:03:84:12 JG05 
G34:45:58:11 JG07 
G35:45:20:41 JG01 
G35:58:20:21 JG03 

因此,如果字符串中的用戶類型:

G33:89:03:20

的5個最近的結果應該在列表框中顯示像這樣:

G33:50:05:11 JG06 
G33:03:84:12 JG05 
G32:86:98:30 JG01 
G32:63:58:11 JG01 
G34:45:58:11 JG07 

我應該poi在這一點上,字符串是座標,「JG」後面的值表示該座標處的某個值。

我得到這些5的方式是通過一塊一塊地穿過字符串。所以用戶輸入「G33」,所以我在開頭找到所有帶G33的人 - 如果沒有,那麼我找到最接近G33的人。那麼它就是「89」,所以我發現所有那些下一部分是「89」的人,如果沒有的話,那麼89就更好了,等等。

我需要知道的是我該如何去做這件事?我已經構建了可視化組件,並且我也有代碼來處理類似的事情,但是當涉及到這個時我真的很難過。正如你可能已經知道,我是相當新的C#,但我學習:)

編輯:查詢碼

private void btnSearch_Click(object sender, EventArgs e) 
     { 
      lstResult.Items.Clear(); 

      if (txtSearch.Text == String.Empty) 
      { 
       MessageBox.Show("The textbox is empty, there is nothing to search.", 
        "Textbox empty", MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
      else 
      { 
       this.CheckFormatting(); 
      } 

     } 

     private long GetIndexForCoord(string coord) 
     { 
      // gets out a numerical value for each coordinate to make it easier to compare 
      Regex m_regex = new Regex("\\d\\d:\\d\\d:\\d\\d:\\d\\d"); 
      string cleaned = m_regex.Match(coord).Value; 
      cleaned = cleaned.Replace(':', '0'); 
      return Convert.ToInt64(cleaned); 
     } 

     private List<string> GetResults(string coord) 
     { 
      // gets out the 5 closest coordinates 
      long index = GetIndexForCoord(coord); 

      // First find the 5 closest indexes to the one we're looking for 
      List<long> found = new List<long>(); 
      while (found.Count < 5) 
      { 
       long closest = long.MaxValue; 
       long closestAbs = long.MaxValue; 
       foreach (long i in m_indexes) 
       { 
        if (!found.Contains(i)) 
        { 
         long absIndex = Math.Abs(index - i); 
         if (absIndex < closestAbs) 
         { 
          closest = i; 
          closestAbs = absIndex; 
         } 
        } 
       } 
       if (closest != long.MaxValue) 
       { 
        found.Add(closest); 
       } 
      } 

      // Then use those indexes to get the coordinates from the dictionary 
      List<string> s = new List<string>(); 
      foreach (long i in found) 
      { 
       s.Add(m_dic[i]); 
      } 
      return s; 
     } 

     private void CheckFormatting() 
     { 
      StringReader objReader = new StringReader(txtSearch.Text); 

      bool FlagCheck = true; 

       if (!Regex.IsMatch(txtSearch.Text, 
        "G3[0-9]{1}:[0-9]{2}:[0-9]{2}:[0-9]{2}")) 
       { 
        FlagCheck = false; 
       } 

      if (FlagCheck == true) 
      { 
       this.CheckAndPopulate(); 
      } 
      else 
      { 
       MessageBox.Show("Your search coordinates are not formatted correctly.", 
         "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 

     private void CheckAndPopulate() 
     { 
      StreamReader objReader = new StreamReader("Jumpgate List.JG"); 
      List<String> v = new List<String>(); 
      do 
      { 
       v.Add(objReader.ReadLine()); 
      } 
      while (objReader.Peek() != -1); 

      objReader.Close(); 

      foreach (string c in v) 
      { 
       long index = GetIndexForCoord(c); 
       m_dic.Add(index, c); 
       m_indexes.Add(index); 
      } 

      List<string> results = GetResults(txtSearch.Text); 
      foreach (string c in results) 
      { 
       lstResult.Items.Add(c); 
      } 
     } 

回答

3

編輯:建議添加代碼的文件中讀取。最後還有一個解釋。
編輯2:添加如果檢查添加到詞典/列表來處理重複。

請注意,這段代碼幾乎肯定效率很低(可能除非偶然),需要清理並且需要添加錯誤處理等,但它可能會給您一個寫入更好代碼的起點最小。 你可能想看看k-nearest neighbor algorithm找出正確的做法。

我假設開頭的字母總是G,並且所有4個部分的座標總是2個數字。

添加以下2類/表格:

Dictionary<long, string> m_dic = new Dictionary<long, string>(); 
    List<long> m_indexes = new List<long>(); 

然後用下面的代碼初始化它們(我假設你已經在所有的座標轉換爲字符串數組讀稱爲v一個每個項目座標):

foreach (string c in v) 
{ 
    long index = GetIndexForCoord(c); 
    if(!m_dic.ContainsKey(index)) 
    { 
     m_dic.Add(index, c); 
     m_indexes.Add(index); 
    } 
} 

然後添加以下2種方法:

// gets out a numerical value for each coordinate to make it easier to compare 
private long GetIndexForCoord(string coord) 
{ 
    Regex m_regex = new Regex("\\d\\d:\\d\\d:\\d\\d:\\d\\d"); 
    string cleaned = m_regex.Match(coord).Value; 
    cleaned = cleaned.Replace(':', '0'); 
    return Convert.ToInt64(cleaned); 
} 
// gets out the 5 closest coordinates 
private List<string> GetResults(string coord) 
{ 
    long index = GetIndexForCoord(coord); 

    // First find the 5 closest indexes to the one we're looking for 
    List<long> found = new List<long>(); 
    while (found.Count < 5) 
    { 
      long closest = long.MaxValue; 
      long closestAbs = long.MaxValue; 
      foreach (long i in m_indexes) 
      { 
       if (!found.Contains(i)) 
       { 
        long absIndex = Math.Abs(index - i); 
        if (absIndex < closestAbs) 
        { 
         closest = i; 
         closestAbs = absIndex; 
        } 
       } 
      } 
      if (closest != long.MaxValue) 
      { 
       found.Add(closest); 
      } 
    } 

    // Then use those indexes to get the coordinates from the dictionary 
    List<string> s = new List<string>(); 
    foreach (long i in found) 
    { 
     s.Add(m_dic[i]); 
    } 
    return s; 
} 

最後,當用戶輸入您在數據發送的數據的方法:

List<string> results = GetResults(lookingFor); 

然後,您可以使用結果來填充您的列表框。

該代碼通過將每個座標轉換爲一個名爲index的數值(因爲它更容易處理)並將所有座標以索引作爲關鍵字添加到字典中。
當它查找最接近的座標時,它會比較您正在查找的索引和每個先前存儲的索引之間的值的差異以找到最接近的5個索引(它使用Math.Abs方法,以便它可以獲得差異不必擔心負數)。這是非常低效的,因爲它爲每個要查找的座標循環一次每個值(因此,如果列表包含1000個座標,並且想要找到最接近的5個座標,則會經過內部循環5000次,我假設通過改進代碼可能會減少到1000倍,爲了更好的算法,我建議查看維基鏈接接近該答案的頂部)。

+0

點的用處。我會看看如果我可以把它變成C#(它看起來像VB.NET對我來說)。我也會看看你發佈的鏈接。謝謝 – Arcadian 2010-07-16 14:39:05

+0

@Arcadian:抱歉,不知道爲什麼我認爲你想在VB中使用它,現在應該會更好。 – 2010-07-16 14:55:01

+0

大聲笑np,我以前用過VB,謝謝你改變它。 – Arcadian 2010-07-16 15:06:02