質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

2991閲覧

C#のdictionary関数でKeyごとに重複している件数を出力する方法

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/10/27 06:45

編集2020/10/27 07:20

目的:C# dictionary関数を使い、Keyが重複している件数をカウントする。
例えば、個人情報4000件とそれぞれの飼い犬/猫の種類が記載されているcsvファイルがあり、このうち、犬の各犬種の割合、猫の各猫種の割合が欲しい。
犬1000件のうちコーギーは200、柴犬500、チワワ300、
猫3000件のうちアメショは1200、ベンガルは800、ペルシャは1000、
のような出力情報が欲しい。

現在dictionaryのKey[0]にそれぞれの種類の値が入っているが、
foreachで各種類をカウントする際の下記の処理の記述に苦戦しています。
-初見の種類には0を入れ、既出の種類には++する。
-最終的に種類ごとにカウントした数を出力する。

素人質問で恐縮ですが、ご回答をお願いいたします。

追記
code

C#

1using 省略 2 3namespace 読み込み 4{ 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 10 var inputFile = @"C:\CSVファイル.txt"; 11 List<string> list = null; 12 Dictionary<string, int> summry = null; 13 14 int DOG9 = 0; 15 int CAT9 = 0; 16 int Total9 = 0; 17 int DOG8 = 0; 18 int CAT8 = 0; 19 int Total8 = 0; 20 int DOG7 = 0; 21 int CAT7 = 0; 22 int Total7 = 0; 23 24 foreach (var line in File.ReadAllLines(inputFile)) 25 { 26 //Dictionaryに入れる 27 if (summry == null) 28 { 29 summry = new Dictionary<string, int>(); 30 continue; 31 } 32 33 //リストにも入れる 34 if (list == null) 35 { 36 list = new List<string>(); 37 continue; 38 } 39 40 41 var clos = line.Split('\t'); 42 string xxx= clos[0]; 43 string xxxx = clos[1]; 44 string xxx = clos[2]; 45 string time = clos[3]; 46 string xxx = clos[4]; 47 string type = clos[5]; 48 string name = clos[6]; ★このカラムの重複数をカウントしたい 49 string xx = $"{xxx} {xxxx}"; 50 51 string MM = Time.Substring(6,1); 52 //Timeの文字列から何月分のデータかを判断する 53 //月ごとに集計が必要 54 55 switch (MM) 56 { 57 //9月分の集計 58 case "9": 59 if (0 <= xxx.IndexOf("DOG")) 60 { 61 DOG9++; 62 //アプリのバージョンを集計する 63 //バージョンが既出でない場合は0を入れて 64 if (summry.ContainsKey(name) == false) 65 { 66 summry.Add(name, 0); 67 } 68 //summry[0]にnameが入っている状態 69 //summry[0]に対して各変数を自動で割り当ててカウントしてほしい 70 71 //なんらかのカウント処理 72 73 } 74 75 else if (0 <= Type.IndexOf("iOS")) 76 { 77 CAT9++; 78 } 79 Total9++; 80 break; 81 82 //8月分の集計 83 case "8": 84 if (0 <= Type.IndexOf("DOG")) 85 { 86 DOG8++; 87 } 88 else if (0 <= Type.IndexOf("iOS")) 89 { 90 CAT8++; 91 } 92 Total8++; 93 break; 94 95 //7月分の集計 96 case "7": 97 if (0 <= Type.IndexOf("DOG")) 98 { 99 DOG7++; 100 } 101 else if (0 <= Type.IndexOf("iOS")) 102 { 103 CAT7++; 104 } 105 Total7++; 106 break; 107 } 108 } 109 110 //月ごとに総数は出力できるようになったがこれはSwitchで分岐したためで 111 //nameは大量の種類があるので自動で初見と既出を判断してカウントする文を書く必要がある 112 System.Console.WriteLine("9月"); 113 System.Console.WriteLine("CAT=" + CAT9); 114 System.Console.WriteLine("DOG=" + DOG9); 115 System.Console.WriteLine("Total=" + Total9 + Environment.NewLine); 116 117 System.Console.WriteLine("8月"); 118 System.Console.WriteLine("CAT=" + CAT8); 119 System.Console.WriteLine("DOG=" + DOG8); 120 System.Console.WriteLine("Total=" + Total8 + Environment.NewLine); 121 122 System.Console.WriteLine("7月"); 123 System.Console.WriteLine("CAT=" + CAT7); 124 System.Console.WriteLine("DOG=" + DOG7); 125 System.Console.WriteLine("Total=" + Total7); 126 127 summry.ToString(); 128 } 129 } 130}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gentaro

2020/10/27 06:52

dictionary関数ってなんですか?
YAmaGNZ

2020/10/27 06:54

情報として、個人情報、犬or猫、犬(猫)の種類の3つがどのように格納されているのか。 (CSVとかそういう話ではなく、コード上での話です。例えばこのような構造体に入っていて、それを配列として持っている等) 現状はどこまで出来ているのか等が分かるようにコードを記載してください。 また、「初見の種類には0を入れ」とありますが、1ではないのですか?
退会済みユーザー

退会済みユーザー

2020/10/27 06:57

Dictionary<string, int>のようなものです。関数という言い方は正しくないかもしれません。
gentaro

2020/10/27 07:00

Dictionary<K, V>クラスでは「重複するKey」というのを認めていませんので、質問の前提条件が成立しないため、回答できません。 既に指摘されていますが、いまどのような実装をしようとしているのか、コードを提示してください。
退会済みユーザー

退会済みユーザー

2020/10/27 07:04

@YAmaGNZ static void Main(string[] args) { var inputFile = @"C:ディレクトパス\CSVファイル.txt"; List<string> list = null; Dictionary<string, int> summry = null; foreach (var line in File.ReadAllLines(inputFile)) { if (summry == null) { summry = new Dictionary<string, int>(); continue; } var clos = line.Split('\t'); string Type = clos[0]; string Name = clos[1]; コード上では上記の格納状態になっています。
YAmaGNZ

2020/10/27 07:10

質問本文は編集できますので、そちらに記載してください。 また、記載されたコードですと中途半端な部分で切れていて、情報がDictionaryには格納されているように見えません。 コードを見る限りCSVを読み込む部分をしっかり作る必要がありそうです。
gentaro

2020/10/27 07:18

Dictionaryのインスタンスをループ内で生成する意味とは…。
退会済みユーザー

退会済みユーザー

2020/10/27 07:22

初見の値に入れるのは1です、これは修正しておきます
gentaro

2020/10/27 07:23

こんなコードにしなくてもCSVの中身を展開したリストを生成してLINQ使えばやりたいことは簡単にできます。 LINQを学習してみてください。
退会済みユーザー

退会済みユーザー

2020/10/27 07:25

DictionaryやKeyを使用することは必須ではなく、 大量のテキストデータのカラムから重複している文字列ごとに件数を集計することが主目的です。 手段が間違っているようであれば集計部分の処理は別の関数を考えますが、二次元配列のデータを効率的に集計する方法としてdictionaryが最も合っていると考えて使用しています。
gentaro

2020/10/27 07:28

いや最も適しているのがそれじゃないからコメントしてるんだけど。 学習する意欲がないなら何言っても無駄なんで別にいいですが。
YAmaGNZ

2020/10/27 08:01

summry["チワワ"]++; でチワワが増えます。 が、1件のデータをクラスや構造体に格納し、それをListなりに格納した後LINQを使用するとかして集計したほうがいいと思われます。
Zuishin

2020/10/27 08:35 編集

まず、File.ReadAllLines() ですが、これはメモリにファイルすべてを読み込むので、巨大なファイルだとメモリを圧迫します。特別な理由がないのであれば File.ReadLines() を使いましょう。これだと行ごとに処理できるのでメモリに優しいです。 グループ毎の集計ですが、GroupBy を使うのが定石です。犬種をキーにすれば、犬種ごとにデータをまとめることができます。 https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.groupby?view=netcore-3.1 まとめた結果は IGrouping<TKey, TElement> になります。 https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.igrouping-2?view=netcore-3.1 まとめたものは ToDictionary で辞書にしましょう。 https://docs.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.todictionary?view=netcore-3.1 File .ReadLines(...) .Select(a => a.Split("\t")) .GroupBy(a => a[6]) .ToDictionary(a => a.Key, a => a.Count()); これで集計終わりです。調べてみてください。
ku__ra__ge

2020/10/27 08:42

本筋には関係ないですが『Dictionary<string, int>のようなもの』はジェネリッククラスと呼びます。ジェネリッククラスはクラスの一種なので単に"Dictionaryクラス"と呼ぶのが普通です。
guest

回答1

0

ベストアンサー

I tried my best.

C#

1static void Main(string[] args) 2{ 3 var DogDic = new Dictionary< string, uint >(); 4 var CatDic = new Dictionary< string, uint >(); 5 6 foreach( string line in File.ReadLines( @"./Test.csv" ) ) 7 { 8 var Cols = line.Split( ',' ); 9 var Class = Cols[5]; 10 var Breed = Cols[6]; 11 12 Dictionary< string, uint > TgtDic = null; 13 { 14 if( Class.Contains( "DOG" ) )TgtDic = DogDic; //犬 15 else if( Class.Contains( "CAT" ) || Class.Contains( "GOD" ) )TgtDic = CatDic; //猫 16 else continue; //This case, this line is just ignored 17 } 18 if( !TgtDic.ContainsKey( Breed ) ){ TgtDic.Add( Breed, 1 ); } 19 else{ ++TgtDic[ Breed ]; } 20 } 21 22 Console.WriteLine( "DOG:" ); 23 foreach( var result in DogDic ){ Console.WriteLine( result.Key + " is " + result.Value.ToString() ); } 24 25 Console.WriteLine(); 26 Console.WriteLine( "CAT:" ); 27 foreach( var result in CatDic ){ Console.WriteLine( result.Key + " is " + result.Value.ToString() ); } 28}

"Test.csv" the sample data file:

Text

1?,?,?,?,?,CAT,ラガマフィン 2?,?,?,?,?,GOD,ラガマフィン 3?,?,?,?,?,DOG,柴 4?,?,?,?,?,CAT,NFC 5?,?,?,?,?,CAT,ラガマフィン 6?,?,?,?,?,CAT,メインクーン 7?,?,?,?,?,DOG,柴 8?,?,?,?,?,DOG,コーギー 9?,?,?,?,?,CAT,トイガー 10?,?,?,?,?,CAT,メインクーン 11?,?,?,?,?,GOD,チート― 12?,?,?,?,?,CAT,チート―

and output result:

Text

1DOG: 2柴 is 2 3コーギー is 1 4 5CAT: 6ラガマフィン is 3 7NFC is 1 8メインクーン is 2 9トイガー is 1 10チート― is 2

投稿2020/10/28 02:55

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問