C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

要素を集計する方法 /チェリー (17/11/11(Sat) 07:55) #85630
Re[1]: 要素を集計する方法 /ぼーちゃん (17/11/11(Sat) 09:13) #85631
  └ Re[2]: 要素を集計する方法 /もりお (17/11/11(Sat) 09:28) #85632
    └ Re[3]: 要素を集計する方法 /チェリー (17/11/11(Sat) 09:47) #85633
      └ Re[4]: 要素を集計する方法 /ぼーちゃん (17/11/11(Sat) 10:39) #85634
        └ Re[5]: 要素を集計する方法 /ぼーちゃん (17/11/11(Sat) 10:44) #85635
          └ Re[6]: 要素を集計する方法 /ぼーちゃん (17/11/11(Sat) 11:08) #85636


親記事 / ▼[ 85631 ]
■85630 / 親階層)  要素を集計する方法
□投稿者/ チェリー (1回)-(2017/11/11(Sat) 07:55:46)

分類:[.NET 全般] 

VB.NETを使っています。


要素数1000程度の文字列配列があり、
その中に、C,O,N,Hなどの元素記号が入っています。

この配列を集計して、
それぞれの元素の数を出力するプログラムを作りたいと考えています。

元素記号は100個程度ありますが、
それらのどれが来るか未知です。

C=0,O=16,N=0,Ca=3

のようにせず、

O=16,Ca=3

のようにして、ゼロが入るものは排除して表示したいと考えています。

自力にやるなら
For文で一つ一つ元素が含まれているか調べていけば良いのですが
非常に面倒なので、簡単にできる方法をお教えください。








[ □ Tree ] 返信 編集キー/

▲[ 85630 ] / ▼[ 85632 ]
■85631 / 1階層)  Re[1]: 要素を集計する方法
□投稿者/ ぼーちゃん (1回)-(2017/11/11(Sat) 09:13:43)
LINQがつかえるなら、まずDistinctで含まれる元素のリストを作ってから
それぞれについてカウントすればよいと思います。

================================================

Dim source As String() = New String() {"O", "Ca", "O", "O", "O", "Ca", "Ca", "Ca", "Ca"}

'含まれる元素のリスト
Dim elementList = source.Distinct()

'含まれる元素ごとに集計
Dim result As New List(Of String)
For Each element As String In elementList
    Dim count As Integer = source.Count(Function(c) c = element)
    result.Add(element & "=" & count)
Next

'表示
Console.WriteLine(String.Join(", ", result))

[ 親 85630 / □ Tree ] 返信 編集キー/

▲[ 85631 ] / ▼[ 85633 ]
■85632 / 2階層)  Re[2]: 要素を集計する方法
□投稿者/ もりお (57回)-(2017/11/11(Sat) 09:28:45)
2017/11/11(Sat) 09:42:40 編集(投稿者)
えい!

Dim symbols = {"O", "O", "Ca"}

Console.WriteLine(symbols _
    .GroupBy(Function(symbol) symbol) _
    .Select(Function(group) String.Format("{0}={1}", group.Key, group.Count())) _
    .Aggregate(Function(a, b) a & "," & b))

[ 親 85630 / □ Tree ] 返信 編集キー/

▲[ 85632 ] / ▼[ 85634 ]
■85633 / 3階層)  Re[3]: 要素を集計する方法
□投稿者/ チェリー (2回)-(2017/11/11(Sat) 09:47:56)
ありがとうございます。
うまくいきました。

ぼーちゃんさんの方法の方がシンプルな気がしますので
こちらを使いたいと思います。

ところで、配列に関してですが
実際には文字列配列ではなく


    Public Class EleInfo

        Property Components As String
	’元素ごとの情報が入ったクラス

    End Class


    Dim source(1000) As EleInfo

のようにして宣言したクラスを使っています。

この場合どのようにしたら良いですか?

自分で改良してみたのですが
これだとうまくいきませんでした。


        '含まれる元素のリスト
        Dim elementList As IEnumerable = source.Distinct()

        '含まれる元素ごとに集計
        Dim result As New List(Of String)
        For Each element As EleInfo In elementList
            Dim count As Integer = source.Count(Function(c) c = element.Components)
            result.Add(element.Components & "=" & count)
        Next

        MsgBox(String.Join(", ", result))


[ 親 85630 / □ Tree ] 返信 編集キー/

▲[ 85633 ] / ▼[ 85635 ]
■85634 / 4階層)  Re[4]: 要素を集計する方法
□投稿者/ ぼーちゃん (2回)-(2017/11/11(Sat) 10:39:37)
> 自分で改良してみたのですが
> これだとうまくいきませんでした。

まずSelectを使って「sourceの集合」から「source.Componentsの集合」へ射影(変換)してください
(意味が分からない場合は是非Selectについて調べてみてください〜)
あとはその射影に対して同じようにDistinctやCountを実行すればいいです

=============================================================================================================

'含まれる元素のリスト
Dim elementList = source.Select(Function(d) d.Components).Distinct()

'含まれる元素ごとに集計
Dim result As New List(Of String)
For Each element As String In elementList
    Dim count As Integer = source.Select(Function(s) s.Components).Count(Function(c) c = element)
    result.Add(element & "=" & count)
Next

MsgBox(String.Join(", ", result))

[ 親 85630 / □ Tree ] 返信 編集キー/

▲[ 85634 ] / ▼[ 85636 ]
■85635 / 5階層)  Re[5]: 要素を集計する方法
□投稿者/ ぼーちゃん (4回)-(2017/11/11(Sat) 10:44:13)
あ、当然ですがsourceの要素のどれかひとつでもNothingだと例外になるので、
そのあたりの対策は追加してください
[ 親 85630 / □ Tree ] 返信 編集キー/

▲[ 85635 ] / 返信無し
■85636 / 6階層)  Re[6]: 要素を集計する方法
□投稿者/ ぼーちゃん (5回)-(2017/11/11(Sat) 11:08:49)
ただ、行数で言えばもりおさんのやり方の方がシンプルですね
クラス配列の場合でも

>.GroupBy(Function(symbol) symbol)
を
.GroupBy(Function(symbol) symbol.Components)

にするだけで対応できるはずです

[ 親 85630 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -