2012-08-22 20 views
1

所以,我有一個列表框,其中有x個項目。在列表框的頂部,我有一個文本框(這是搜索字段)。我嘗試開發一種從列表框中刪除項目的算法,如果它不包含搜索詞(代碼中的可變關鍵字)。這應該發生在用戶鍵入的每個鍵上(即時)。所以,代碼:在列表框中的即時搜索算法

private void _keywordTextBox_TextChanged(object sender, EventArgs e) 
    { 
     string keyword = _keywordTextBox.Text; 

     if (keyword == searchtext || isSpace) // do nothing if space is typed - searchtext is a templatetext in the textbox ("type here to search...") 
      return; // ignore 
     else if (keyword == "") 
     { 
      listBox.Items.Clear(); 

      foreach (string s in originalList) 
       listBox.Items.Add(s); 
     } 
     else 
     { 
      List<string> selection = new List<string>(); 

      foreach (string s in originalList) // originalList is the listbox at startup 
       selection.Add(s); 

      listBox.BeginUpdate(); 
      string[] keywordSplit = keyword.Split(' '); 

      try 
      { 
       for (int i = originalList.Count - 1; i >= 0; i--) 
       { 
        string[] selectionSplit = selection[i].Split(' '); 

        int l = 0; // number of hits 

        for (int j = 0; j < selectionSplit.Length; j++) 
        { 
         for (int k = 0; k < keywordSplit.Length; k++) 
         { 
          if (selectionSplit[j].ToLower().Contains(keywordSplit[k].ToLower())) 
          { 
           l++; 
           break; 
          } 
         } 
        } 

        if (l < keywordSplit.Length) // Not hit on all keywords 
         selection.RemoveAt(i); 
       } 
      } 
      finally 
      { 
       listBox.Items.Clear(); 

       foreach (string s in selection) // Add selection in listbox 
        listBox.Items.Add(s); 

       if (listBox.Items.Count > 0) 
        listBox.SetSelected(0, true); // Select first item in listbox 

       listBox.EndUpdate(); 
      } 
     } 
    } 

這個問題很難描述,除非它不按預期工作。據我所知,行爲是零星的。

如果我搜索「CK流」,我應該得到一個命中計算器。更重要的是,它也應該工作,如果我刪除字符(刪除退格鍵)。任何人?

編輯:更多細節:

列表框應該收縮和增長的每次擊鍵,根據什麼用戶搜索。列表框應該保留每個與用戶輸入的關鍵字匹配的項目,並過濾掉不匹配的項目。

+0

我想你說的功能試圖實現是由微軟的'ComboBox'提供'AutoComplete'功能,請參閱http://stackoverflow.com/questions/6243611/combobox-and-autocomplete-in-c-sharp – yogi

+0

請詳細解釋代碼的預期用途。哪些元素應顯示或過濾?也許舉一些更多的例子。 – waldrumpus

+0

@yogi否:)它只搜索字符串的開頭,不在中間。 – raze

回答

1

你的代碼太頻繁地增加。例如;

帶有搜索詞'aaa bbb'的文本'aaa aaa aaa'會給出l的3,因爲每次找到'aaa'時都會增加l。所以即使'bbb'從未被發現,這將是一場比賽。

您可以通過在每次搜索新選擇行之前刪除找到的關鍵字片斷部分並重新創建關鍵字片段來解決此問題。

l++; 
break; 

成爲

l++ 
keywordSplit.RemoveAt[k]; 
break; 

和移動

string[] keywordSplit = keyword.Split(' '); 

你開始第k循環

Altough我覺得有可能是更好的方法來達到你想要什麼之前它應該工作一點清潔和更快的代碼。

+0

是的,我同意你的意見。但在這一點上,我只是想讓它工作,以便我可以看到邏輯。後綴,我可以嘗試優化它。我現在將測試您的更改。謝謝! – raze

+0

這不起作用。 keywordSplit是一個數組,所以它不能刪除這樣的項目。 – raze

0

我得到它的工作。 @IvoTops幫助我朝着正確的方向發展。只需先循環搜索所有關鍵字,然後再選擇。

   for (int j = 0; j < keywordSplit.Length; j++) 
       { 
        for (int k = 0; k < selectionSplit.Length; k++) 
        { 
         if (selectionSplit[k].ToLower().Contains(keywordSplit[j].ToLower())) 
         { 
          l++; 
          break; 
         } 
        } 
       } 

似乎現在工作正常。

2

或者你可以嘗試制定出一個正則表達式:

private void textBox1_TextChanged(object sender, EventArgs e) 
{ 
    string keyword = textBox1.Text; 
    if (string.IsNullOrEmpty(keyword.Trim())) 
    { 
     listBox1.Items.Clear(); 
     listBox1.Items.AddRange(_originalList.ToArray()); 
    } 
    else 
    { 
     Regex regex = new Regex(GetRegexPatternFromKeyword(keyword)); 
     List<string> selection = 
      _originalList.Where(s => regex.IsMatch(s)).ToList(); 
     listBox1.Items.Clear(); 
     listBox1.Items.AddRange(selection.ToArray()); 
    } 
} 

private static string GetRegexPatternFromKeyword(string keyword) 
{ 
    string[] words = 
     keyword.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(word => "(?=.*" + word.Replace(")", @"\)") + ")").ToArray(); 
    return string.Join("", words); 
} 

免責聲明:可能會有一些情況下,輸入會「摧毀」的正則表達式模式

+0

似乎工作。謝謝。但不是正則表達式使用緩慢?這並不重要,因爲我有最多100件物品。 – raze

+0

有100個項目,我不會太擔心。 – fguchelaar