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

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

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

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

Q&A

解決済

3回答

1610閲覧

Hashtableについて

fruitpunch

総合スコア6

C#

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

0グッド

0クリップ

投稿2021/10/21 22:50

編集2021/10/21 23:34

前提・実現したいこと

C#のHashtableに入っているデータ(単語)をカウントして一番多く出現した単語をアウトプットすることに挑戦してるところですが、たとえば、apple ,apple, bananaがHashtableに入ってるならappleをアウトプットする。
一番多い単語が一個しかない場合は実現できたものの、もしこれがapple,apple,banana,bananaとなったとき最後のbananaしかアウトプットできません。
appleとbanana両方アウトプットする方法はありますか??

該当のソースコード

C#

1static void Main(string[] args) 2 { 3 //テキストファイルの中の単語をリストに 4 string filePath = ("file path"); 5 6 List<string> lines = File.ReadAllLines(filePath).ToList(); 7 8 Hashtable ht = new Hashtable(); 9 10 int count = 1; 11 //time complexity O(n) 12 //because this loop should loop through every single line 13 foreach (string line in lines) 14 { 15 if (ht.ContainsKey(line)) 16 { 17 ht[line] = (int)ht[line] + 1; 18 19 } 20 else 21 { 22 ht.Add(line, count); 23 } 24 25 } 26 27 //print hashtable 28 //time complexity O(n) 29 //because this loop should loop through every single line 30 foreach (DictionaryEntry entry in ht) 31 { 32 Console.WriteLine("Key: " + entry.Key + " / " + "Value: " + entry.Value); 33 } 34 35 maxFreq(ht); 36 Console.ReadKey(); 37 } 38 public static void maxFreq(Hashtable ht) 39 { 40 string key = ""; 41 int max = 0; 42 43 //loop throught the hashtable 44 //time complexity O(n) 45 //because this loop should loop through every single line 46 foreach (DictionaryEntry entry in ht) 47 { 48 if ((int)entry.Value > max) 49 { 50 max = (int)entry.Value; 51 key = (string)entry.Key; 52 } 53 } 54 55 Console.WriteLine("The maximum frequency word is: " + key);

if の中にif (ht.ContainsKey(max)){Console.WriteLine("The maximum frequency word is: " + key);}を試してもうまく行きませんでした。
めちゃくちゃ初心者な質問で申し訳無いですが、なにかアドバイスいただけたら嬉しいです。
よろしくおねがいします。

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

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

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

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

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

Zuishin

2021/10/21 23:11

課題にしては Hashtable の使い方がよくありませんが、これは何ですか? 課題だとしたら参考にしているサイトがよくないと思います。 そうでないとしたら Hashtable ではなく List<string> を使えば混乱が少なくなるのではないでしょうか。 var list = new List<string> { "apple", "banana", "banana" }; var word = list.GroupBy(a => a).OrderByDescending(a => a.Count()).First().Key; // グループ化して多い順に並べ替えて一番多い単語を word に入れる Console.WriteLine(word);
退会済みユーザー

退会済みユーザー

2021/10/21 23:20

maxFreq(Hashtable ht) メソッドの引数に渡す Hashtable をどのように生成しているかのサンプルを書いてください。
dodox86

2021/10/21 23:30

> apple,apple,banana,bananaとなったとき 質問者さん自身が問題を誤解して質問文がおかしくなっている可能性がありますが、キーが果物の名前で、値が果物の個数 なのかもしれませんね。 var hash = new Hashtable() { { "apple", 2 }, { "banana", 2 } }; いずれにせよコメントをいただいているようにHashtableをどのように生成しているか、ちゃんと具体的に示しましょう。>質問者さん
fruitpunch

2021/10/21 23:36

Zuishinさん ご回答ありがとうございます。 海外のサイトで勉強していて、Hashtableの中にテキストファイルの内容を入れるタスクでしたが、自分で色々ためしてたらこういう質問がでてきました。
fruitpunch

2021/10/21 23:38

SurferOnWwwさん dodox86さん ご回答ありがとうございます。 コード更新しました。 わかりづらくてすみませんでした。
退会済みユーザー

退会済みユーザー

2021/10/21 23:41

ダメな場合の List<string> lines の例も書いてもらえませんか? どれがどうなって欲しいのかも。
fruitpunch

2021/10/21 23:56

SurferOnWwwさん apple,apple,banana,banana4つの単語が入っているテキストファイルをHashtableに入れて Key: apple Value: 2 Key: banana Value: 2 をアウトプットするということに挑戦してまして、これについては問題なく実現できました。今やろうとしていることは、このHashtableに入っている単語で一番出現回数が多い単語をアウトプットするというタスクです。自分のコードでは一番出現回数が多い単語が一つの場合なら問題なく反映されるんですが、apple,apple,banana,bananaのようにapple2回banana2回の場合bananaしか反映されないんです。 もしできるならappleとbanana両方アウトプットしたいですが、そこで躓いています。わかりづらい質問すみませんでした。
退会済みユーザー

退会済みユーザー

2021/10/22 00:29

> apple,apple,banana,banana4つの単語が入っているテキストファイルをHashtableに入れて そのテキストファイルから読んできて変数 lines に代入するのは以下のコードと同じになると想像してます。 List<string> lines = new List<string> { "apple", "apple", "banana", "banana" }; であれば、Hashtable など使わなくても、Linq を使って lines を直接操作すれば望む結果が得られると思うのですが? わざわざ Hashtable を使っているのは勉強のため? そうだとしても今は Hashtable は非推奨で、代わりに Dictionary<TKey, TValue> を使うよう推奨されてます。 > 海外のサイトで勉強していて とのことですが、かなり古い記事では? であれば、もっと新しい記事で勉強した方が良いのではないですか?
fruitpunch

2021/10/22 01:02

SurferOnWwwさん 返信ありがとうございます。 今はHashtableの基本的な文法や使い方について勉強しているところでして、ご指摘していただいた部分を参考に別のサイトを探してみます。 わざわざありがとうございました。
guest

回答3

0

すでにベストアンサーがついていて今更ながらですが、質問のコメント欄で書いたように Hashtable は非推奨で、代わりに Dictionary<TKey, TValue> を使うよう推奨されているということで、Dictionary<string, int> を使った案を書いておきます。

そうすれば Linq が使えます。下のコードの MaxValueWords メソッドを見てください。慣れないとループで処理するより分かり難いかもしれませんが、Linq が使えないと時代に取り残されますので、積極的に使うことをお勧めします。

using System; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Collections.Generic; using System.Linq; namespace ConsoleApp2 { class Program { static void Main(string[] args) { List<string> lines = new List<string> { "apple", "apple", "banana", "banana", "orange" }; var dictionary = new Dictionary<string, int>(); foreach (string line in lines) { if (dictionary.ContainsKey(line)) { dictionary[line]++; } else { dictionary.Add(line, 1); } } foreach (KeyValuePair<string, int> entry in dictionary) { Console.WriteLine("Key: " + entry.Key + " / " + "Value: " + entry.Value); } MaxValueWords(dictionary); Console.ReadKey(); } public static void MaxValueWords(Dictionary<string, int> dictionary) { var words2 = dictionary .Where(p => p.Value == dictionary.Max(p2 => p2.Value)) .Select(p => p.Key); Console.WriteLine("The maximum frequency words are:"); foreach(string word in words2) { Console.WriteLine(word); } } } }

結果は:

イメージ説明

投稿2021/10/22 02:07

編集2021/10/22 05:39
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

fruitpunch

2021/10/22 02:47

貴重なアドバイスいただきありがとうございます! SQLっぽくてメソッド構文を理解するのにちょっと時間かかりましたが、FindAll メソッドとConvertAll メソッドをWhereとSelectに置き換えてるんですね。 foreach文より簡潔に書けるのはいいですね。 大変いい勉強になりました!! Linqについて勉強します。 ありがとうございました!
BluOxy

2021/10/22 05:34

> words2 ここだけ typo しています
退会済みユーザー

退会済みユーザー

2021/10/22 05:40

ご指摘ありがとうございました。訂正しておきました。
guest

0

ベストアンサー

同率一位を、あるだけ出したい様なので、ループを2回、回す感じかな。

C#

1public static void maxFreq(Hashtable ht) 2{ 3 int max = 0; 4 foreach (DictionaryEntry entry in ht) 5 { 6 if ((int)entry.Value > max) 7 { 8 max = (int)entry.Value; 9 } 10 } 11 12 foreach (DictionaryEntry entry in ht) 13 { 14 if ((int)entry.Value == max) 15 { 16 key = (string)entry.Key; 17 Console.WriteLine("The maximum frequency word is: " + key); 18 } 19 } 20}

こんな感じですかね。

投稿2021/10/22 00:19

seek

総合スコア32

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

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

fruitpunch

2021/10/22 00:33

アドバイスありがとうございます! まさに求めていた答えでした!! 二回ループするとは全く思いつかなかったです いい勉強になりました!
dodox86

2021/10/22 00:38

@質問者さん > 二回ループするとは全く思いつかなかったです 初心の方にどうも多く見受けられるようですが、たぶんコード優先で、コードを書けば、あるいはそんなコードの定型があって、それを使えば要望の答えが出ると思っている部分があるのだと思います。 > {Console.WriteLine("The maximum frequency word is: " + key);}を試してもうまく行きませんでした。 そうではなく、例えば紙とペンと自分の頭を使って解くときにどうイメージできるか、です。で、コードに書き起こすだけです。頭の中でできていなければ決してコードに書けません。
fruitpunch

2021/10/22 01:12

@dodox86さん 確かにコード優先でとりあえずコーディングすることに重点をおいてました。 ご指摘頂いたようにまずは紙に書いて図や文字にして考えがまとまってからコードを書くステップに進むように気を付けます。 わざわざありがとうございます。
guest

0

ご参考まで

C#

1class Program 2{ 3 static void Main(string[] args) { 4 //テキストファイルの中の単語をリストに 5 string filePath = ("file path"); 6 List<string> lines = File.ReadAllLines(filePath).ToList(); 7 HashSet<string> hsst = new HashSet<string>(lines.Select(x => x)); 8 var dict = new Dictionary<string, int>(hsst.ToDictionary(x=>x, x=>lines.Count(n => n == x))); 9 foreach (var entry in dict) { 10 Console.WriteLine("Key: " + entry.Key + " / " + "Value: " + entry.Value); 11 } 12 MaxFreq(dict); 13 Console.ReadKey(); 14 } 15 public static void MaxFreq(Dictionary<string, int> dict) { 16 var max = dict.Max(x => x.Value); 17 var items = dict.Where(x => x.Value == max).Select(x => x.Key); 18 Console.WriteLine($"The maximum frequency words are: { string.Join(", ", items)}"); 19 } 20}

GroupBy 使うとスマートですね。

C#

1class Program 2{ 3 static void Main(string[] args) { 4 //テキストファイルの中の単語をリストに 5 string filePath = ("file path"); 6 List<string> lines = File.ReadAllLines(filePath).ToList(); 7 var max = lines.GroupBy(x => x).Max(x => x.Count()); 8 var items = lines.GroupBy(x => x).Where(x => x.Count() == max).Select(x => x.Key).ToList(); 9 Console.WriteLine($"The maximum frequency words are: { string.Join(", ", items)}"); 10 Console.ReadKey(); 11 } 12}

投稿2021/10/22 04:58

lehshell

総合スコア1147

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問