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

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

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

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

Q&A

解決済

2回答

344閲覧

同じkeyの数を数えるプログラムの作成

kanayawa1

総合スコア6

C#

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

0グッド

1クリップ

投稿2020/06/01 13:14

前提・実現したいこと

日付ごとのユーザーのアクセス回数を集計する。

2019-10-18 user:Me
2019-10-18 user:Mother
2019-10-18 user:Me
2019-10-18 user:Father
2019-10-18 user:Father

上記のようなログからC#で日付ごとの各ユーザーのアクセス回数を集計しようとしています。
しかし、重複しているuserを数えるコードの作成ができません。
最終的に下記のような形にしたいです。
2019-10-18,Me,2
2019-10-18,Mother,1
2019-10-18,Father,2

該当のソースコード

C#

1static void main(){ 2 System.IO.StreamReader file =new System.IO.StreamReader(@"c:\test.txt"); //ログを読み込む 3while((line = file.ReadLine()) != null) 4{ 5 string date = line.Substring(0,10); //日付を抜き出す 6 string user = line.Substring(16,18); //userを抜き出す 7   string key = date + ',' + user; //日付とuserを一つにする 8    9} 10}

試したこと

言い訳になってしまいますが、
C#を始めて一週間であるためここからどのようにすれば良のかが分かりません。
どなたかお力を貸していただけないでしょうか?

補足情報(FW/ツールのバージョンなど)

Visual Stadioを使用しています。

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

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

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

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

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

BluOxy

2020/06/01 14:07

他の言語は触ったことがあるでしょうか。C#が始めてなら、その内容はハードルが高すぎると思います。
kanayawa1

2020/06/01 14:10

ほとんどプログラミングを行ったことはありません。しかし、業務で必要であるため、C#の習得が必要となり、勉強をしています。よろしければ、回答お願いいたします。
guest

回答2

0

ベストアンサー

BluOxyさんのおっしゃる通りですが、コード書いてみました。

cs

1 class Program { 2 static void Main(string[] args) { 3 //入力 4 Dictionary<Log, int> Logs = new Dictionary<Log, int>();//ログを入力する入れ物 5 using (System.IO.StreamReader file = new System.IO.StreamReader(@"test.txt")) { 6 string line = null; 7 while ((line = file.ReadLine()) != null) { 8 Log l = new Log(line); 9 if (Logs.ContainsKey(l)) {//日付、誰のパターンがすでにあるか確認 10 Logs[l]++;//すでにある場合は増やす 11 } else { 12 Logs.Add(l, 1);//ない場合は新たに追加する 13 } 14 } 15 } 16 17 //出力 18 string output = null; 19 foreach (Log l in Logs.Keys) { 20 output += l.Date + "," + l.Who + "," + Logs[l] + "\r\n"; 21 } 22 Console.WriteLine(output.Substring(0, output.Length - 2));//最後の改行を消して出力 23 Console.Read(); 24 } 25 } 26 public class Log { 27 public string Date;//日付が入る 28 public string Who;//Me,Mother,Fatherが入る 29 public Log(string line) { 30 string[] parts = line.Split(' '); 31 string[] user = parts[1].Split(':'); 32 Date = parts[0]; 33 Who = user[1]; 34 } 35 public override bool Equals(object obj) {//ContainsKeyに必要 36 if (obj is Log) { 37 var l = (Log)obj; 38 return this.Date==l.Date && this.Who==l.Who; 39 } else { 40 return false; 41 } 42 } 43 public override int GetHashCode() {//ContainsKeyに必要 44 return this.GetType().ToString().Length; 45 } 46 }

投稿2020/06/01 16:37

Hey_CH

総合スコア437

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

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

0

前提

言い訳になってしまいますが、

C#を始めて一週間であるためここからどのようにすれば良のかが分かりません。
どなたかお力を貸していただけないでしょうか?

仰る通り、言い訳です。
C#を始めて一週間であるからといって、考えるのを止めて良い理由にはなりません。
そこを直さないと初心者からは抜けられないことを認識してください。

回答

実現したいことの難易度やkanayawa1さんのスキルを踏まえると、プログラムの書き方を先に学んだ方が良いです。

プログラムの書き方

どのようにすれば良のかが分かりません。

kanayawa1さんの実現したいことをそのままプログラムにすれば良いのです。
この質問の根本問題はその方法が分からないことです。

そもそも「プログラム」とはなんでしょうか。
プログラムには何事も インプット(入力) があって、 アウトプット(出力) があります。
そして、インプットからアウトプットに変換する処理 があります。

日付ごとのユーザーのアクセス回数を集計する

kanayawa1さんがそれを作りたいというのであれば、まずは インプット と アウトプット が何かを洗い出してください。

今回の場合は下記がインプットで

2019-10-18 user:Me 2019-10-18 user:Mother 2019-10-18 user:Me 2019-10-18 user:Father 2019-10-18 user:Father

下記がアウトプットですね。

2019-10-18,Me,2 2019-10-18,Mother,1 2019-10-18,Father,2

もっと問題を小さくするならば、2019-10-18 user:Meの入力したとき2019-10-18,Me,1と出力すれば要件を満たしているのではないでしょうか。

ここまではコーディング一切無しで問題解決に必要な情報だけを考えてきました。
インプットとアウトプットが固まってきたら、それを実現する手段である C# と絡めていきます。

C# ベースでインプット と アウトプットを考える

C# では型の概念が存在します。C# で処理を作りたければ、インプットが何の型でアウトプットが何の型かを常に考える必要があります。

インプットの型は文字列なので1行ずつ処理する場合は string です。数行の文字列を処理する場合はstringではなくstringを要素に持つコレクションが良いでしょう。

アウトプットは複数行でかつ、日付とユーザ、アクセス回数を識別する必要があるため、オブジェクト型のコレクションもしくはKeyが日付とユーザ名、Valueがアクセス回数のDictionaryが良いでしょう。
※コレクション、Dictionaryについては後述

では、C#においてインプットとアウトプットはどこに実装するのでしょうか。

C#でコーディングする際はまずクラスを定義してからメソッドを定義します。
そして、メソッドに実処理を記述することができます。

この内、C#における インプット とは メソッドの引数 (もしくはクラス内のメンバー)のことで
C#における アウトプット とは メソッドの戻り値 (もしくはクラス内のメンバー)のことです。

なぜクラスをまたいでメソッドを定義しなければならないのか。それは C# がオブジェクト指向言語だからです。
ここは、話がそれるので詳しい説明は割愛します。

コレクションって?

今回の場合では、文字列を切ったり繋いだりするだけでも頑張れば実現できるかもしれません。
しかし、コレクションを覚えて使うことで文字列を気合で処理するよりかは非常に楽に作れます。
詳しくはリンク先のページを見たり、「C# コレクション」と検索してください。

さらに書くと、KeyとValueにひも付けて保持するコレクションであるDictionaryクラスを使う方法が1番簡単だと思います。

ここまで前提の説明をして、ようやくC#に関係のある回答

ログからC#で日付ごとの各ユーザーのアクセス回数を集計しようとしています。

しかし、重複しているuserを数えるコードの作成ができません。

メソッドを定義して下記実装を行えば良いのです。

  1. 取得した日付とユーザーをKeyに、アクセス回数をValueに指定したDictionaryオブジェクトを生成
  2. テキストの1行から「日付」と「ユーザー」を取得
  3. Dictionaryに「日付」と「ユーザー」に対応するKeyが存在するならば、対応するValueをインクリメントする
  4. Dictionaryの各要素をループで取得し、各要素のKeyとValueを表示

Dictionaryを使う方法が恐らく1番簡単なので、その方向性で解説しました。

最後に

コードの書き方とC#の基礎について、最低限のことを書きました。
あとは内容さえ理解できれば実践できるはずです。

正直な話、上記の内容がC#を始めて1週間のkanayawa1さんにとってハードルが高いであろうことは承知の上ですが、そういう問題に手をつけているという事は理解してください。

難しいようであれば、一度この問題を解くのはやめて、もっと簡単な物から作ることをお勧めします。
業務であれば、上司に「難易度が高い」とアラートを投げてください。

余談

LINQを覚えることでさらにスマートに処理が実現できます。(今回の場合だとGroupByメソッドが使える)
しかし、コレクションを理解した前提の機能なので、学習コストは高いです。紹介だけに留めます。

投稿2020/06/01 14:59

編集2020/06/01 16:20
BluOxy

総合スコア2663

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

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

kanayawa1

2020/06/03 12:11

無事、完成させることができました。ありがとうございます。少しずつでも、C#の勉強を進めていきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問