- 題名: System.Collectionの使い方について。
- 日時: 2009/12/17 13:26:14
- ID: 26079
- この記事の返信元:
- (なし)
- この記事への返信:
- [26080] Re[1]: System.Collectionの使い方について。2009/12/17 15:05:30
- ツリーを表示
■No26079に返信(たいちうさんの記事)
> Dim words As String() = Split("This is a pen. That is a book.")
>
> Dim hash As New Hashtable
> For i As Integer = 0 To words.Length - 1
> hash(words(i)) = CInt(hash(words(i))) + 1
> Next
これは、それぞれの単語の出現回数を数えているのですよね。
処理方法としては、単純で良いと思います。ただし、この手法だと、
・空白が2つ以上連続した場合、空文字列が単語としてカウントされてしまう。
・"government of the people, by the people, for the people." の場合、
"people"×3ではなく、"people,"×2 と"people."×1 としてカウントされる。
といった問題はあります。
> Dim list As New SortedList
SortedList を使っているのは、並び替えのためでしょうか?
この場合、元の Hashtable に
hash("the") = 20
hash("It") = 15
が追加されると、並び順は
20 : the
15 : It
2 : is
2 : a
1 : This
(以下略)
ではなく、
20 : the
2 : is
2 : a
15 : It
1 : This
(以下略)
となってしまいます。
> HashtableやSortedListの使用には拘りませんが、
DataTable/DataView を使うのは如何でしょうか?
これならば、並び順を自由に変更できます。
Dim words() As String = Split("This is a pen. That is a book.")
Dim dt As New DataTable()
dt.CaseSensitive = True '単語の大文字小文字を区別するなら True
dt.PrimaryKey = New DataColumn() {dt.Columns.Add("word", GetType(String))}
dt.Columns.Add("count", GetType(Integer))
For Each word As String In words
Dim row As DataRow = dt.Rows.Find(word)
If row Is Nothing Then
dt.Rows.Add(New Object() {word, 1})
Else
row("count") += 1
End If
Next
Dim view As New DataView(dt)
view.Sort = "count DESC, word ASC"
Console.WriteLine("出現回数の降順")
For Each row As DataRowView In view
Console.WriteLine(String.Format("{0} : {1}", row("count"), row("word")))
Next
view.RowFilter = "count>=2"
Console.WriteLine("複数回出現した単語")
For Each row As DataRowView In view
Console.WriteLine(String.Format("{0} : {1}", row("count"), row("word")))
Next
' quit
Console.WriteLine("End.")
Console.Read()
■No26082に返信(たいちうさんの記事)
> 今回の質問の意図ですが、「単語を出現頻度順に表示する」という程度の
> 単純な事をするのに、HashtableとSortedListを2段階で使うことに無駄を感じ、
> もっと簡単な方法を求めている、ということでした。
2003 が相手となると、私もそのぐらいしか思いつきませんでした。
2008 だと簡単なのですけれどね…。
Dim Words() As String = Split("This is a pen. That is a book.")
Dim q = From Word In Words _
Group By Word Into Count() _
Order By Count Descending, Word Ascending
For Each x In q
Console.WriteLine(x.Count & " : " & x.Word)
Next
分類:[.NET]
はじめまして。たいちうと申します。 VB .NET 2003のCollectionについての質問です。 単語の出現頻度を求めるためのサンプルを作ってみたのですが、 SortedListやHashtableの使い方にかなり無駄が多いと思います。 Private Structure MyData Public key As String Public value As Integer End Structure Sub Main() Dim words As String() = Split("This is a pen. That is a book.") Dim hash As New Hashtable For i As Integer = 0 To words.Length - 1 hash(words(i)) = CInt(hash(words(i))) + 1 Next Dim list As New SortedList Dim seq As Integer = 0 For Each key As String In hash.Keys Dim data As New MyData data.key = key data.value = hash(key) list.Add(hash(key) & ": " & seq, data) seq = seq + 1 Next For i As Integer = list.Count - 1 To 0 Step -1 Dim data As MyData = list.GetByIndex(i) Console.WriteLine(data.value & " : " & data.key) Next i ' quit Console.WriteLine("End.") Console.Read() End Sub 要するに、 "This is a pen. That is a book." ↓ 2 : a 2 : is 1 : book. 1 : That 1 : pen. 1 : This という変換ができれば良いのですが、これしか思いつきませんでした。 もっと良い方法を教えていただけないでしょうか。 HashtableやSortedListの使用には拘りませんが、 シンプルな方法がありがたいです。効率面も特に重視はしていません。