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

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

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

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

Q&A

解決済

2回答

4038閲覧

C#: List<string>を格納するListの重複をなくしたい

Kumaaicho

総合スコア11

C#

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

0グッド

0クリップ

投稿2019/05/21 22:51

実現したいこと

お世話になります。C#にて、高速に配列処理を実施したく、下記のようなことを実現できないか検討しております。

子リスト「List<string>」 を格納する親Listへ、子Listを重複なくAddしたい。
具体的には、下記コードとなります。

該当のソースコード

List<List<string>> parentList = new List<List<string>>(); List<string> list1 = new List<string>() { "a", "b" }; List<string> list2 = new List<string>() { "a", "c" }; List<string> list3 = new List<string>() { "a", "b" }; parentList.Add(list1); parentList.Add(list2); parentList.Add(list3); // 内容が重複しているので、Addされないようにしたい

試したこと

list1 と list3は内容が同じなので、
list1.SequenceEqual(list3);
と実行すると、trueが戻り、内容の判定ができることはわかりました。
しかし、Addする際に毎回すべての子List要素をForループでSequenceEqualにて判定すると処理速度が低下してしまうため、他に良い方法がないか検討しております。

もし、良い方法がございましたらご教示いただければ幸いです。

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

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

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

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

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

Zuishin

2019/05/21 22:57

List<string> を使う限り高速化は難しい気がします。これの使用法と、子要素の条件によってはできるかもしれません。
k.matsuda

2019/05/22 00:19

とりあえずすべての要素をListに入れてから、重複を削除するのはどうでしょう?
Kumaaicho

2019/05/22 01:14

Zuishin様、k.matsuda 様 ご回答ありがとうございます。初めての投稿にこんなに早くレスポンス頂き感動しております。 >List<string> を使う限り高速化は難しい… List<string>であるとその後のデータ取り扱いが便利になりますのでこのような形式を検討しておりましたが、最悪は改行コードなどを区切り文字とした連結文字列にする、という案を採用しようかと考えています。 >とりあえずすべての要素をListに入れてから、重複を削除… この方法にて、「Distinct」というメソッドを試してみましたが、うまく重複削除されず断念しました。Distinctの使い方が間違っているかもしれませんので、もう少し検討してみます。
Zuishin

2019/05/22 01:17

これの使用法と、子要素の条件によってはできるかもしれません。
Zuishin

2019/05/22 01:24

たとえば要素の数が二つと決まっているなら List<string> の代わりにタプルが使えるので次のようにできます。 var source= new List<(string, string)>() { ("a", "b"), ("a", "c"), ("a", "b") }; var dest = source.ToHashSet().ToList();
Zuishin

2019/05/22 01:25

あるいは var dest = source.Distinct().ToList();
Zuishin

2019/05/22 01:28 編集

これは「たとえば」の話で、要素の数によらず Distinct を使うこともできますが、List<string> のままでは使えません。
Kumaaicho

2019/05/22 03:24

Zuishin様 ご回答ありがとうございました。今回の要件では要素数は可変でしたので、Distinct方式で検討を進めてみたいと思います。
guest

回答2

0

ベストアンサー

C#

1 class ListEqualityComparer : IEqualityComparer<List<string>> 2 { 3 public bool Equals(List<string> list1, List<string> list2) 4 { 5 return list1.SequenceEqual(list2); 6 } 7 8 public int GetHashCode(List<string> list1) 9 { 10 return list1.ToArray().GetHashCode(); 11 } 12 }

C#

1 parentList = parentList.Distinct(new ListEqualityComparer()).ToList();

要素数が2と決まっているのならば、

C#

1 parentList = parentList.GroupBy(a => new { First = a.First(), Last = a.Last() }).Select(g => g.First()).ToList();

投稿2019/05/22 01:37

x_x

総合スコア13749

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

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

Kumaaicho

2019/05/22 03:22

x_x様 ご回答ありがとうございます。ご教示いただいたソースコードを実行したところ、Distinctにて重複がカットされませんでした。そこで、以下のように修正してみたところ、期待通り重複カットされるようになりました。 ```C# class ListEqualityComparer : IEqualityComparer<List<string>> { public bool Equals(List<string> list1, List<string> list2) { return list1.SequenceEqual(list2); } public int GetHashCode(List<string> list1) { //return list1.ToArray().GetHashCode(); return string.Join(",", list1.ToArray()).GetHashCode(); } } ``` まずは、こちらの方法で処理速度を測定し実用性を確認させていただきます。ありがとうございました。
guest

0

C#は使ったことないですが、javaだとSetがあるので調べてみたら、こんなのありました。
C# HashSetのサンプル

同じものなら上書きされるかと思います~

あと、、、

どういう経緯でこのようなコードになったのかはわかり得ませんが、
list1~3 のリスト、サイズ固定の配列ではだめなんでしょうか?
可変にする理由がないのであれば、固定長の方が処理速度上がりそうな。。。
(C#をあまりわかっていないので、ただの余談ですが。)

投稿2019/05/22 00:17

kaputaros

総合スコア1844

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

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

Zuishin

2019/05/22 01:17

ハッシュが要素と無関係なのでそのままでは使えません。 またサイズ固定でも処理速度は上がりません。
Kumaaicho

2019/05/22 01:22

kaputaros様 ご回答ありがとうございます。HashSetにつきましては、以下のように確認してみました。 HashSet<List<string>> ts = new HashSet<List<string>>(); ts.Add(list1); ts.Add(list2); ts.Add(list3); 当初、list3がAddされないことを期待しておりましたが、残念ながら追加できてしまいました…。 また、list1~3は要素数が可変になりますので、固定配列にはできないという制約がございます。 もう少し、HashSet関係で解決策がないか、検討してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問