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

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

新規登録して質問してみよう
ただいま回答率
85.47%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

C#

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

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

4回答

1695閲覧

二重のforループをLINQへ

locoJr.

総合スコア15

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

C#

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

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

0クリップ

投稿2019/03/11 15:30

編集2019/03/14 20:18

■事前情報
クラスA
クラスB
クラスC
があるとします。

クラスAはList<クラスB>をプロパティで持ちます。
クラスBはList<クラスC>をプロパティで持ちます。
つまり、クラスAとクラスBは1:n、クラスBとクラスCも1:nという関係になり、ツリー構造で構成されています。

■本題
とあるクラスCの1要素が判明している状態で、それが含まれるクラスBを特定する内容のLINQを検討していました。
for文では思いつくのですが、LINQでなかなか取得できません。

C#

1for(int b=0;b<クラスB.Count;b++;){ 2 for(int c=0;c<クラスC.Count;c++;){ 3 if(クラスA.クラスB[b].クラスC[c] == 判明しているクラスC){ 4 クラスB B=クラスA.クラスB[b]; 5 }; 6 }; 7};

直接オブジェクトを取得するやり方と、indexを取得して参照するやり方とあるかと思いますが、ご助力をお願いできないでしょうか。


2019/03/15追記
クラスB群、クラスC群は全て異なる要素になっています。
つまり、特定のクラスC要素であれば、特定のクラスBが導出可能です。
上記情報が漏れておりました。

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

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

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

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

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

guest

回答4

0

ベストアンサー

こんなかな?

C#

1class Program 2{ 3 public static void Main(string[] args) 4 { 5 var soruce = new ClassA 6 { 7 ClassBs = new List<ClassB> 8 { 9 new ClassB 10 { 11 ClassCs = new List<ClassC> 12 { 13 new ClassC 14 { 15 Element = 0 16 }, 17 new ClassC 18 { 19 Element = 1 20 } 21 } 22 }, 23 new ClassB 24 { 25 ClassCs = new List<ClassC> 26 { 27 new ClassC 28 { 29 Element = 2 30 }, 31 new ClassC 32 { 33 Element = 3 34 } 35 } 36 } 37 } 38 }; 39 40 var fixedC = new ClassC 41 { 42 Element = 2 43 }; 44 45 var foundBs = soruce.ClassBs 46 .Where(b => b.ClassCs 47 .Where(c => c.Element == fixedC.Element).Any()); 48 } 49 50} 51 52class ClassA 53{ 54 public List<ClassB> ClassBs { get; set; } 55} 56 57class ClassB 58{ 59 public List<ClassC> ClassCs { get; set; } 60} 61 62class ClassC 63{ 64 public int Element { get; set; } 65}

投稿2019/03/12 03:12

hihijiji

総合スコア4150

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

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

locoJr.

2019/03/14 20:34

ご回答ありがとうございます。 foundBs = soruce.ClassBs .Where(b => b.ClassCs .Where(c => c.Element == fixedC.Element)); までは考えていたのですが、boolにしないといけないところでひっかかりできていませんでした。 Anyをつければ良かったのですね。 追記したようにクラスBとクラスCは重複なく存在するため、以下のようになりました。 クラスB foundB = source.ClassBs.Where(b => b.ClassCs.Where(c => c.Element == fixedC.Element).Any()).First();
guest

0

個人的には、普通にネストしてしまったほうがわかりやすくていいんじゃないかな?って思います。

foreach(var res in a.classB.Where(b => b.classC.Contains(searchTarget))) foreach(var res in a.classB.Where(b => b.classC.Any(c => c.ID == searchTarget.ID))) // 最初の一つだけでいいならWhereをFirstかFirstOrDefaultにする res = a.classB.FirstOrDefault(b => b.classC.Contains(searchTarget));

嫌がる人は嫌がると思いますけれども。

投稿2019/03/12 02:56

moredeep

総合スコア1507

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

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

locoJr.

2019/03/14 20:30

ご回答ありがとうございます。 なるほど、一つのLINQにしてしまうのではなく、あえて分けることで整理しやすくなりますね。 またどうしようか悩んだら、まず分けて整理してみたいと思います。
guest

0

SelectManyで2重のシーケンスを展開して(BとCのタプルにして)やって、それをフィルタにかけたらいいです。

C#

1foreach(var found in listB.SelectMany(b => b.listC, (classB, classC) => (classB, classC)) 2 .Where(bc => bc.classC == knownClassC) 3 .Select(bc => bc.classB)) 4{ 5 6} 7

もし対象となるCが1つしかないとわかっているなら、First/FirstOrDefaultで。

C#

1var found = listB.SelectMany(b => b.listC, (classB, classC) => (classB, classC)) 2 .Where(bc => bc.classC == knownClassC) 3 .Select(bc => bc.classB) 4 .First();

※ C#7.1以上でコンパイルしてください。

投稿2019/03/11 16:37

編集2019/03/12 13:03
toki_td

総合スコア2850

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

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

Zuishin

2019/03/11 23:45

考え方は正しいと思いますが、コードが間違っていませんか?
toki_td

2019/03/12 13:04

ホントだ、、、テストコードから回答用に書き換えたときに盛大にミスってました、、、 ご指摘ありがとうございます。
locoJr.

2019/03/14 20:23 編集

ご回答ありがとうございます。 タプルが何なのかこれまで気にした事がありませんでしたが、ご回答いただいた内容を踏まえ確認し、意味や使い方をそれとなく把握することができました。 今回はなぜかC#7.0でやるという、意味不明なプロジェクトのおかげ(せい)で、使用するこができませんでしたが、頭の引き出しに入れたいと思います。 ---------- 追記 バージョンを明記すべきでしたね。
guest

0

(1) クラスBにbool HasSomeProperDescriptionOfC(ClassC needle)を作ります

csharp

1public bool HasSomeProperDescriptionOfC(ClassC needle) => privateContainerOfC.Contains(needle);

※classなんでContainsが上手く動作するようIEquatable<T>を実装するなど手当してください。

(2) クラスAで、Whereをします

csharp

1var thoseWhoHasClassC = this.privateContainerOfB.Where(b => b.HasSomeProperDescriptionOfC(target));

投稿2019/03/12 01:05

papinianus

総合スコア12705

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

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

locoJr.

2019/03/14 20:26

ご回答ありがとうございます。 なるほど、クラスB自身に探索する機能を設けても良かったのですね。 別の機会に試してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問