2011-05-05 121 views
2

我是WPF新手,所以這可能是一個簡單的問題。我有一個應用程序,從csv文件中讀取一些單詞並將它們存儲在一個字符串列表中。我試圖做的是將這個列表參數化以顯示我列表中最流行的單詞。所以在我的用戶界面中我想要一個文本框,當我輸入數字時5會過濾原始列表,只留下新列表中5個最常用(頻繁)的單詞。任何人都可以協助完成最後一步嗎?謝謝 -WPF列表過濾

public class VM 
{ 
    public VM() 
    { 
     Words = LoadWords(fileList); 
    } 

    public IEnumerable<string> Words { get; private set; } 

    string[] fileList = Directory.GetFiles(@"Z:\My Documents\", "*.csv"); 


    private static IEnumerable<string> LoadWords(String[] fileList) 
    { 

     List<String> words = new List<String>(); 
     // 
     if (fileList.Length == 1) 
     { 

      try 
      { 
       foreach (String line in File.ReadAllLines(fileList[0])) 
       { 
        string[] rows = line.Split(','); 

        words.AddRange(rows); 
       } 

      } 
      catch (Exception ex) 
      { 
       System.Windows.MessageBox.Show(ex.Message, "Problem!"); 
      } 

     } 

     else 
     { 
      System.Windows.MessageBox.Show("Please ensure that you have ONE read file in the source folder.", "Problem!"); 

     } 
     return words; 
    } 

} 

回答

1

一個LINQ查詢,由該單詞降序的字和順序的順序應該做它。試試這個

private static IEnumerable<string> GetTopWords(int Count) 
{ 
    var popularWords = (from w in words     
      group w by w 
      into grp 
      orderby grp.Count() descending 
      select grp.Key).Take(Count).ToList(); 
    return popularWords; 
} 
1

你可以使用CollectionViewSource.GetDefaultView(viewModel.Words),它返回ICollectionView

ICollectionView曝光FilterPredicate<object>類型的屬性,您可能需要進行篩選。

因此,常見的情況是這樣的:

  1. 視圖模型公開財產PopularCount,即綁定在查看一些文本。
  2. ViewModel監聽PopularCount屬性的更改。
  3. 通知時發生,模型獲得ICollectionView中viewModel.Words收集並設置Filter屬性。

您可以找到Filter property usage的工作示例here。如果您遇到代碼困擾,請告訴我。

0

我不知道,如果「字」名單的分組和排序是你想要什麼,但如果是的話,這可能是做這件事的方式:

int topN = 3; 
    List<string> topNWords = new List<string>(); 

    string[] words = new string[] { 
     "word5", 
     "word1", 
     "word1", 
     "word1", 
     "word2", 
     "word2", 
     "word2", 
     "word3", 
     "word3", 
     "word4", 
     "word5", 
     "word6", 
    }; 

    // [linq query][1] 
    var wordGroups = from s in words 
         group s by s into g 
         select new { Count = g.Count(), Word = g.Key }; 

    for (int i = 0; i < Math.Min(topN, wordGroups.Count()); i++) 
    { 
     // (g) => g.Count is a [lambda expression][2] 
     // .OrderBy and Reverse are IEnumerable extension methods 
     var element = wordGroups.OrderBy((g) => g.Count).Reverse().ElementAt(i); 
     topNWords.Add(element.Count + " - " + element.Word); 
    } 

Thsi可以通過使用進行更短訂購linq SELECT子句中,但我想向你介紹內嵌lambdas和IEnumerable擴展了。

短的版本可能是:

topNWords = (from s in words     
      group s by s 
      into g 
      orderby g.Count() descending 
      select g.Key).Take(Math.Min(topN, g.Count()).ToList(); 
0

而不是閱讀所有的話到列表中,然後根據頻率進行排序,更清潔的方法是創建一個自定義類MyWord存儲字和頻率。在閱讀文件時,單詞的頻率可以增加。該類可以實現IComparable<T>來比較基於頻率的單詞。

public class MyWord : IComparable<MyWord> 
{ 
    public MyWord(string word) 
    { 
     this.Word = word; 
     this.Frequency = 0; 
    } 

    public MyWord(string word, int frequency) 
    { 
     this.Word = word; 
     this.Frequency = frequency; 
    } 

    public string Word { get; private set;}   
    public int Frequency { get; private set;} 

    public void IncrementFrequency() 
    { 
     this.Frequency++; 
    } 

    public void DecrementFrequency() 
    { 
     this.Frequency--; 
    } 

    public int CompareTo(MyWord secondWord) 
    { 
     return this.Frequency.CompareTo(secondWord.Frequency); 
    } 
} 

主類​​會對這些成員,

public IEnumerable<MyWord> Words { get; private set; } 

private void ShowMostPopularWords(int numberOfWords) 
{ 
    SortMyWordsDescending(); 
    listBox1.Items.Clear(); 

    for (int i = 0; i < numberOfWords; i++) 
    { 
     listBox1.Items.Add(this.Words.ElementAt(i).Word + "|" + this.Words.ElementAt(i).Frequency); 
    } 
} 

並調用ShowMostPopularWords()

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    int numberOfWords; 
    if(Int32.TryParse(textBox1.Text, NumberStyles.Integer, CultureInfo.CurrentUICulture, out numberOfWords)) 
    { 
     ShowMostPopularWords(numberOfWords); 
    } 
}