C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[12]: C#での繰り返し文


(過去ログ 133 を表示中)

[トピック内 16 記事 (1 - 16 表示)]  << 0 >>

■78608 / inTopicNo.1)  C#での繰り返し文
  
□投稿者/ D (1回)-(2016/01/28(Thu) 13:09:02)

分類:[C#] 

2016/01/28(Thu) 13:25:29 編集(投稿者)

はじめまして、C#を初めて数か月です。
プログラムの経験はJavaとCを1年程度です。
今回の質問はC#での冗長的なif文の改善をしたくて、教えていただきたいです。

以下に、内容を記します。

・作成物
グループとIDを紐付けて、IDごとのオペ履歴をExcel出力の機能

・環境
Visual Studio 2013
ASP.NET 4.5

・修正したいもの
グループの変更回数に制限が2回になってしまっているので上限をなくしたい
※if文と変数を増やすのはやめたい

・テーブル
ID_HIS (id, no, date) IDがグループNo.を変更(新規作成)したときに作成されるテーブルです
※同日に別なグループNo.への日付の重複があり得ます。
GROUP_HIS (no, ope, start, end) グループのオペを記録しているテーブルです
※開始(start)してから終了(end)まではIDの移動はないとします

・現在のプログラム
foreach (var idlist in Colection) // Colectionは選択されたIDとする
{

// グループNo.とIDを紐付
var i_g = (from a in DbContext.ID_HIS
where a.id == idlist.id
orderby a.time, a.no ascending
select a).FirstOrDefault();

// IDがグループを変えた回数をカウント
var count = (from b in DbContext.ID_HIS
where i_g.id == a.id
&& i_g.no != b.no
select b).Count();

// グループの経歴のコレクションを作成
var his = from d in DbContext.GROUP_HIS
where (d.no == i_g.no
&& d.start < loss_date
orderby d.start ascending
select d;

// IDが1回グループを変えたときのグループと日付を取得
var i_g_2 = (from a2 DbContext.ID_HIS
where i_g.id == a2.id
&& i_g.no != a2.no
&& i_g.date <= a2.date
orderby a2.date, a2.no ascending
select a2).FirstOrDefalt();

var i_g_3 = i_g_2;

// IDがグループを1回以上変えたときのグループの経歴コレクション
if (count > 0)
{
his = from d in DbContex.GROUP_HIS
where (d.no == d.no
&& d.start < i_g_2.date)
|| (d.no == d.no
&& d.start >= i_g_2.date)
orderby d.start ascending
select d;

if (count > 1)
{
i_g_3 = (from a3 in DbContext.ID_HIS
where i_g.id == a3.id
&& i_g.no != a3.no
&& i_g_2.lot_no != a3.no
&& i_g_2.date <= a3.date
orderby a3.date, a3.no ascending
select a3).FirstOrDefalt();

his = from d in DbContex.GROUP_HIS
where (d.no == d.no
&& d.start < i_g_2.date)
|| (d.no == d.no
&& d.start >= i_g_2.date
&& d.start < i_g_3.date)
|| d.no == i_g_3.no
&& d.start >= i_g_3.date)
orderby d.start ascending
select d;
}
}
// 帳票出力用のコレクションを作成
foreach (var igcol in his)
{
var history = new History(idlist)
hist.ope = igcol.ope
hist.id = idlist.id
hist.no = igcol.no
hist.start = igcol.no
hist.end = igcol.no
idlist.Histories.Add(hist);
}
}

AddRangeを使えればいいのでしょうけど、使うとSystem.Collections.Genericをusingで定義しているのに、usingディレクティブやアセンブリ参照が不足してしまうと出てしまうため使えませんでした。
説明が不足していましたらすみません。
よろしくお願いいたします。
引用返信 編集キー/
■78610 / inTopicNo.2)  Re[1]: C#での繰り返し文
□投稿者/ WebSurfer (799回)-(2016/01/28(Thu) 19:00:17)
No78608 (D さん) に返信

もう少し分かりやすく書けないでしょうか?

質問内容を理解するにはアップされたコードを読む必要がありそうです
が、読みたい気持ちが起きないですし、それを克服して読んだとしても
全体の内容を理解するのに大事な情報は他にもありそうで、結局分から
ないような気がするのですが・・・

> AddRangeを使えればいいのでしょうけど、

それで問題の一部でも解決するなら、まずはそこに絞って質問してはい
かがでしょう?
引用返信 編集キー/
■78619 / inTopicNo.3)  Re[2]: C#での繰り返し文
□投稿者/ D (2回)-(2016/01/29(Fri) 12:02:02)
No78610 (WebSurfer さん) に返信
> ■No78608 (D さん) に返信
>
> もう少し分かりやすく書けないでしょうか?
>
> 質問内容を理解するにはアップされたコードを読む必要がありそうです
> が、読みたい気持ちが起きないですし、それを克服して読んだとしても
> 全体の内容を理解するのに大事な情報は他にもありそうで、結局分から
> ないような気がするのですが・・・
>
>>AddRangeを使えればいいのでしょうけど、
>
> それで問題の一部でも解決するなら、まずはそこに絞って質問してはい
> かがでしょう?

いくつかの問題を含んでいるためわかりづらくなってしまっています。

おそらくプログラムに慣れてないからだと思うのですが
実際のソースをそのままだと5倍ぐらい複雑なので、2点に要点だけをしぼってみます

1.IF文を繰り返し使ってしまうことに関して
人物のオペ履歴(his)を求めます
そのためには、グループの移動履歴があるテーブル(ID_HIS)と、
グループ全体の共通オペ履歴を管理しているテーブル(GROUP_HIS)を参照する必要があります
これまで移動回数は3回までとしてましたが、無制限にしたいと思ってます

現在のソース(count:移動回数、i_g:IDとGROUPの紐付)

his = IDを単純に紐付けたGROUP_HISテーブル
IF(count =>1)
{ i_g_2 = 1回目の移動後の紐付
his = 存在期間によりi_gとi_g_2を紐付けたGROUPテーブル
IF(count =>2)
{ i_g_3 = 2回目の移動後の紐付
His = 存在期間によりi_g、i_g_2、i_g_3を紐付けたGROUPテーブル
}
}

上記を移動回数が増えてもi_g_4とかを使わずに結果を抽出したいと思ってます。


2.AddRangeが使えない事象について
実は1か月以上前から検索したり、調べたりしているのですが、まったく理由が分かりません。
エラーの意味はusingに登録されていないって意味だと思うのですが、
System.Collections.Generic;は登録してあり、Systemや、System.Collectionsを登録しても
「'System.Linq.IOrderedQueryable<*.Models.*>' に 'AddRange' の定義が含まれておらず、
型 'System.Linq.IOrderedQueryable<*.Models.*>' の最初の引数を受け付ける拡張メソッドが見つかりませんでした。
using ディレクティブまたはアセンブリ参照が不足しています。」
と出てしまい、ダメでした。
上記のエラーで何時間も検索して調べたのですが、私の能力が不足しているせいか見つかりませんでした。


内容が分かりづらく、大変申し訳ありませんが、ご助力お願いいたします。


引用返信 編集キー/
■78620 / inTopicNo.4)  Re[3]: C#での繰り返し文
□投稿者/ WebSurfer (800回)-(2016/01/29(Fri) 13:08:10)
No78619 (D さん) に返信

> おそらくプログラムに慣れてないからだと思うのですが

それ以前の質問の仕方の問題だと思うのですが・・・

掲示板の向こう側にいて、掲示板に書いてあること以外は知り得ない第三者に、どのような
情報を提供すれば、質問者さんの課題・問題を理解してもらえるかをよく考えて質問するの
が重要だと思います。

何が問題かというと、例えば、凡人の自分の場合ですが、

> 1.IF文を繰り返し使ってしまうことに関して
> 人物のオペ履歴(his)を求めます
> そのためには、グループの移動履歴があるテーブル(ID_HIS)と、
> グループ全体の共通オペ履歴を管理しているテーブル(GROUP_HIS)を参照する必要があります
> これまで移動回数は3回までとしてましたが、無制限にしたいと思ってます

で「人物」「オペ」「グループ」「移動」「テーブル」と言われてもそれが何だか分からない
ので、その先を考える気力がなくなってしまいます。

気力を振り絞ってその先を読むと、IF(count =>1) ... IF(count =>2) ... IF(count =>n) の
ようにコーディングすると n までしか対応できないが、それを無制限にしたいのであろうと
いうことはなんとなく理解できます。

でも、「人物」「オペ」「グループ」「移動」「テーブル」とか、その後に出てくる「紐付」
とかが何だか分からないので的確な答は出せません。

そういう質問者さん固有の用語を第三者に理解できるように説明すれば何とかなるという話でも
なさそうです。(それはかなり難しいでしょうし、説明してもらっても多分ほとんどの人は読む
気がしないと思います)

なので、そういう質問者さん固有の言葉は使わないで、一般的に誰でも理解できる用語を使って
質問者さんの課題・問題を説明していただくことが重要ではないかと思います。


> 2.AddRangeが使えない事象について

これについても具体的に第三者に分かるように、例えば、極短いサンプルコードをアップして、
回答者の方でもそれをコピペすれば問題を再現できるようにしてもらえると、話が早いかと
思います。

なお、コードをアップする場合は[投稿モード]を[図表モード]にしてください。

引用返信 編集キー/
■78621 / inTopicNo.5)  Re[4]: C#での繰り返し文
□投稿者/ D (3回)-(2016/01/29(Fri) 16:17:04)
D さんの Web サイト
2016/01/29(Fri) 16:23:22 編集(投稿者)
No78620 (WebSurfer さん) に返信
> ■No78619 (D さん) に返信
> 
>>おそらくプログラムに慣れてないからだと思うのですが
> 
> それ以前の質問の仕方の問題だと思うのですが・・・
> 
> 掲示板の向こう側にいて、掲示板に書いてあること以外は知り得ない第三者に、どのような
> 情報を提供すれば、質問者さんの課題・問題を理解してもらえるかをよく考えて質問するの
> が重要だと思います。
> 
> 何が問題かというと、例えば、凡人の自分の場合ですが、
> 
>>1.IF文を繰り返し使ってしまうことに関して
>>人物のオペ履歴(his)を求めます
>>そのためには、グループの移動履歴があるテーブル(ID_HIS)と、
>>グループ全体の共通オペ履歴を管理しているテーブル(GROUP_HIS)を参照する必要があります
>>これまで移動回数は3回までとしてましたが、無制限にしたいと思ってます
> 
> で「人物」「オペ」「グループ」「移動」「テーブル」と言われてもそれが何だか分からない
> ので、その先を考える気力がなくなってしまいます。
> 
> 気力を振り絞ってその先を読むと、IF(count =>1) ... IF(count =>2) ... IF(count =>n) の
> ようにコーディングすると n までしか対応できないが、それを無制限にしたいのであろうと
> いうことはなんとなく理解できます。
> 
> でも、「人物」「オペ」「グループ」「移動」「テーブル」とか、その後に出てくる「紐付」
> とかが何だか分からないので的確な答は出せません。
> 
> そういう質問者さん固有の用語を第三者に理解できるように説明すれば何とかなるという話でも
> なさそうです。(それはかなり難しいでしょうし、説明してもらっても多分ほとんどの人は読む
> 気がしないと思います)
> 
> なので、そういう質問者さん固有の言葉は使わないで、一般的に誰でも理解できる用語を使って
> 質問者さんの課題・問題を説明していただくことが重要ではないかと思います。
> 
> 
>>2.AddRangeが使えない事象について
> 
> これについても具体的に第三者に分かるように、例えば、極短いサンプルコードをアップして、
> 回答者の方でもそれをコピペすれば問題を再現できるようにしてもらえると、話が早いかと
> 思います。
> 
> なお、コードをアップする場合は[投稿モード]を[図表モード]にしてください。
> 

ご丁寧にありがとうございます。
図表モードで投稿いたします。

IF文のソースを抽象的に書いてみました。
Aテーブルと、BテーブルはUrlに画像で張り付けました。

var a1 = (from a in A
          where a.key2 = "A-1"
          orderby a.time ascending
          select a).FirstOrDefault();
		
int c = (from c in A
         where c.key2 = "A-1"
         select c).Count();

var b = from b in B
        where b.key1 = a1.key1
        orderby b.time ascending
        select b;

var a2 = a1;

if(c => 2)
{
         a2 = (from a in A
               where a.key2 = a1.key2
               && a.key1 != a1.key2
               && a.time >= a1.time
               orderby a.time ascending
               select a)FirstOrDefault();
	
	 b = from b in B
             where b.key1 = a1.key1
             && b.time < a2.time
             || b.key1 = a2.key2
             && b.time => a2.time
             orderby b.time ascending
             select b;
}

これだと、itemの'け'が出てこなくなってしまいます。
IF文をたくさん使わずに出せるようになる方法を教えていただきたいです。
よろしくお願いいたします。

また、AddRangeにかんしては、新規プロジェクトで例文を作成したところ動いてしまったため、現環境で動かないのがやはりわかりません。
もう少し自分で調べてみます。

引用返信 編集キー/
■78622 / inTopicNo.6)  Re[5]: C#での繰り返し文
□投稿者/ WebSurfer (801回)-(2016/01/29(Fri) 16:59:07)
No78621 (D さん) に返信

> Aテーブルと、BテーブルはUrlに画像で張り付けました。

見つけられません。どこでしょう?


#引用は必要最小限にとどめてください。
引用返信 編集キー/
■78623 / inTopicNo.7)  Re[6]: C#での繰り返し文
□投稿者/ D (4回)-(2016/01/29(Fri) 17:08:57)
D さんの Web サイト
No78622 (WebSurfer さん) に返信
> ■No78621 (D さん) に返信
>
>>Aテーブルと、BテーブルはUrlに画像で張り付けました。
>
> 見つけられません。どこでしょう?
>
>
> #引用は必要最小限にとどめてください。

Webサイト(任意)に張り付けてました。

ここに直リンを張りますね。
http://s1.gazo.cc/up/174076.png
引用返信 編集キー/
■78624 / inTopicNo.8)  Re[7]: C#での繰り返し文
□投稿者/ WebSurfer (802回)-(2016/01/29(Fri) 21:19:42)
No78623 (D さん) に返信

> ここに直リンを張りますね。
> http://s1.gazo.cc/up/174076.png

そのテーブルをベースにどういうことをしたいか説明していただけませんか。

とりあえず、質問者さんのやりたいことを想像してコードを書いてみました。コメント
の「// こういうことがしたい?」以下を見てください。説明は、すみませんが明日に
させてください。結果を見てやりたいことと違うか否かを考えておいてください。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleAppLinq2
{
    public class A
    {
        public string key1 { get; set; }
        public string key2 { get; set; }
        public DateTime time { get; set; }
    }

    public class B
    {
        public string key1 { get; set; }
        public string item { get; set; }
        public DateTime time { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            List<A> listA = new List<A> {
                new A { key1 = "A", key2 = "A-1", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "A", key2 = "A-2", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "A", key2 = "A-3", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "B", key2 = "A-1", time = DateTime.Parse("2016/1/11") },
                new A { key1 = "B", key2 = "A-2", time = DateTime.Parse("2016/1/16") },
                new A { key1 = "C", key2 = "A-1", time = DateTime.Parse("2016/1/21") }
            };

            List<B> listB = new List<B> {
                new B { key1 = "A", item = "あ", time = DateTime.Parse("2016/1/4") },
                new B { key1 = "A", item = "い", time = DateTime.Parse("2016/1/14") },
                new B { key1 = "A", item = "う", time = DateTime.Parse("2016/1/24") },
                new B { key1 = "B", item = "え", time = DateTime.Parse("2016/1/5") },
                new B { key1 = "B", item = "お", time = DateTime.Parse("2016/1/15") },
                new B { key1 = "B", item = "か", time = DateTime.Parse("2016/1/25") },
                new B { key1 = "C", item = "き", time = DateTime.Parse("2016/1/6") },
                new B { key1 = "C", item = "く", time = DateTime.Parse("2016/1/16") },
                new B { key1 = "C", item = "け", time = DateTime.Parse("2016/1/26") }
            };

            var a1 = (from a in listA
                      where a.key2 == "A-1"
                      orderby a.time ascending
                      select a).FirstOrDefault();

            int c = (from a in listA
                     where a.key2 == "A-1"
                     select a).Count();

            var b = from a in listB
                    where a.key1 == a1.key1
                    orderby a.time ascending
                    select a;

            Console.WriteLine("a1: key1={0}, key2={1}, time={2}", a1.key1, a1.key2, a1.time);
            Console.WriteLine("c={0}", c);
            foreach (var x in b)
            {
                Console.WriteLine("b: key1={0}, item={1}, time={2}", x.key1, x.item, x.time);
            }

            var a2 = a1;

            if(c >= 2)
            {
                a2 = (from a in listA
                    where a.key2 == a1.key2
                    && a.key1 != a1.key2
                    && a.time >= a1.time
                    orderby a.time ascending
                    select a).FirstOrDefault();
	
	            b = from a in listB
                    where a.key1 == a1.key1
                    && a.time < a2.time
                    || a.key1 == a2.key2
                    && a.time >= a2.time
                    orderby a.time ascending
                    select a;

                Console.WriteLine("a2: key1={0}, key2={1}, time={2}", a2.key1, a2.key2, a2.time);
                foreach (var x in b)
                {
                    Console.WriteLine("b: key1={0}, item={1}, time={2}", x.key1, x.item, x.time);
                }
            }

            /*
            質問者さんのコードのとおり(間違いは訂正)。結果は:
            a1: key1=A, key2=A-1, time=2016/01/01 0:00:00
            c=3
            b: key1=A, item=あ, time=2016/01/04 0:00:00
            b: key1=A, item=い, time=2016/01/14 0:00:00
            b: key1=A, item=う, time=2016/01/24 0:00:00
            a2: key1=A, key2=A-1, time=2016/01/01 0:00:00
            */

            // こういうことがしたい?
            var result = from itemB in listB
                         join itemA in listA
                         on itemB.key1 equals itemA.key1
                         where itemB.time >= itemA.time && itemA.key2 == "A-1"
                         select itemB;

            foreach (var x in result)
            {
                Console.WriteLine("b: key1={0}, item={1}, time={2}", x.key1, x.item, x.time);
            }

            /*
            結果は:
            b: key1=A, item=あ, time=2016/01/04 0:00:00
            b: key1=A, item=い, time=2016/01/14 0:00:00
            b: key1=A, item=う, time=2016/01/24 0:00:00
            b: key1=B, item=お, time=2016/01/15 0:00:00
            b: key1=B, item=か, time=2016/01/25 0:00:00
            b: key1=C, item=け, time=2016/01/26 0:00:00
            */
        }
    }    
}

引用返信 編集キー/
■78626 / inTopicNo.9)  Re[7]: C#での繰り返し文
□投稿者/ WebSurfer (803回)-(2016/01/30(Sat) 11:15:24)
No78623 (D さん) に返信

先のレスでアップしたコード:

var result = from itemB in listB
             join itemA in listA
             on itemB.key1 equals itemA.key1
             where itemB.time >= itemA.time && itemA.key2 == "A-1"
             select itemB;

の説明ですが、join 句を使った内部結合(参考 URL 下記)を利用し、

(1) テーブル A と B で key1 が同じ、
(2) テーブル A と B で time が B の方が遅いか同じ、
(3) テーブル A で key2 が "A-1"

の 3 条件に合うテーブル B のレコードを抽出しています。

方法 : 内部結合を実行する (C# プログラミング ガイド)
https://msdn.microsoft.com/ja-jp/library/bb397941.aspx

引用返信 編集キー/
■78627 / inTopicNo.10)  Re[8]: C#での繰り返し文
□投稿者/ D (5回)-(2016/01/30(Sat) 17:41:37)
2016/01/30(Sat) 18:13:55 編集(投稿者)
No78626 (WebSurfer さん) に返信
> ■No78623 (D さん) に返信
> 
> 先のレスでアップしたコード:
> 
> var result = from itemB in listB
>              join itemA in listA
>              on itemB.key1 equals itemA.key1
>              where itemB.time >= itemA.time && itemA.key2 == "A-1"
>              select itemB;
> 
> の説明ですが、join 句を使った内部結合(参考 URL 下記)を利用し、
> 
> (1) テーブル A と B で key1 が同じ、
> (2) テーブル A と B で time が B の方が遅いか同じ、
> (3) テーブル A で key2 が "A-1"
> 
> の 3 条件に合うテーブル B のレコードを抽出しています。
> 
> 方法 : 内部結合を実行する (C# プログラミング ガイド)
> https://msdn.microsoft.com/ja-jp/library/bb397941.aspx

出力でどのようなことをしたいかまで想像していただいて、結果を出していただきありがとうございました。

それで大変申し訳ないのですが、求めていたものは少し違います。

結果は:
A-1をキー項目として
A.key2,B.key1,B.item,B.time
A1,A,あ,2016/01/01 0:00:00
A1,B,お,2016/01/15 0:00:00
A1,C,け,2016/01/26 0:00:00

という結果を出力したいです。

現在のコードだと、

A1,A,あ,2016/01/01 0:00:00
A1,B,お,2016/01/15 0:00:00

までしかでてきません。
//if文の前に
      var a3 = a1;
//前if文の閉じる前に
            if(c >= 3)
            {
                a3 = (from a in listA
                    where a.key2 == a1.key2
                    && a.key1 != a2.key2
                    && a.time >= a2.time
                    orderby a.time ascending
                    select a).FirstOrDefault();

	            b = from a in listB
                    where (a.key1 == a1.key1
                    && a.time < a2.time)
                    || (a.key1 == a2.key2
                    && a.time >= a2.time
                    && a.time < a3.time)
                    || (a.key1 == a3.key2
                    && a.time >= a3.time)
                    orderby a.time ascending
                    select a;

上記の文を追加してみたら、目的の結果は出すことはできますが、
それだと、A-1のkey1がDというパターンになった時に、更に変数の定義とIF文を追加する必要が出てきます。

たびたび申し訳ありません。

引用返信 編集キー/
■78644 / inTopicNo.11)  Re[9]: C#での繰り返し文
□投稿者/ 朱鷺 (1回)-(2016/01/31(Sun) 23:43:23)
No78627 (D さん) に返信

> 結果は:
> A-1をキー項目として
> A.key2,B.key1,B.item,B.time
> A1,A,あ,2016/01/01 0:00:00
> A1,B,お,2016/01/15 0:00:00
> A1,C,け,2016/01/26 0:00:00
> 
> という結果を出力したいです。

横から失礼します。投稿は初めてなので不備があれば申し訳ございません。
下記コードではお望みの結果となるでしょうか?
(No78624のWebSerferさんのサンプルコードのListB作成部以降を下記に置き換えます)。

            //key2のリストを作成
            var key2List = (from a in listA
                     orderby a.time ascending
                     select a.key2).Distinct();
            //key2がA-1の時だけ必要なのであればforeachで回す必要はありません。
            foreach ( var key in key2List)
            {
                //key2の値がkeyと等しいものを抽出
                var aList = (from a in listA
                             where a.key2  == key
                             orderby a.key1 ascending
                             select a);
                foreach (var al in aList)
                {
                    //listBのkey2がalのkey2と等しいかつlistBのtimeがalのtime以降のもので
                    //最も日付が古いものを抽出
                    var result = (from b in listB
                                  where al.time <= b.time && al.key1 == b.key1
                                  orderby b.time ascending
                                  select new { al.key2, b.key1, b.item, b.time }).FirstOrDefault();
                    if (result != null)
                    {
                        Console.WriteLine(result.key2.Replace("-", "") + "," + result.key1 + "," + result.item + "," + result.time);
                    }
                }
            }

引用返信 編集キー/
■78645 / inTopicNo.12)  Re[9]: C#での繰り返し文
□投稿者/ WebSurfer (804回)-(2016/02/01(Mon) 01:16:14)
No78627 (D さん) に返信

先にお願いしましたけど、

> ここに直リンを張りますね。
> http://s1.gazo.cc/up/174076.png

そのテーブルをベースにどういうことをしたいか説明していただけませんか。

掲示板に書いてあること以外何も知り得ない第三者にわかる言葉で書いてくださいね。
引用返信 編集キー/
■78646 / inTopicNo.13)  Re[10]: C#での繰り返し文
□投稿者/ D (6回)-(2016/02/01(Mon) 09:21:13)
No78644 (朱鷺 さん) に返信
> ■No78627 (D さん) に返信
>
>>結果は:
>>A-1をキー項目として
>>A.key2,B.key1,B.item,B.time
>>A1,A,あ,2016/01/01 0:00:00
>>A1,B,お,2016/01/15 0:00:00
>>A1,C,け,2016/01/26 0:00:00
>>
>>という結果を出力したいです。
>
> 横から失礼します。投稿は初めてなので不備があれば申し訳ございません。
> 下記コードではお望みの結果となるでしょうか?
> (No78624のWebSerferさんのサンプルコードのListB作成部以降を下記に置き換えます)。
>
> //key2のリストを作成
> var key2List = (from a in listA
> orderby a.time ascending
> select a.key2).Distinct();
> //key2がA-1の時だけ必要なのであればforeachで回す必要はありません。
> foreach ( var key in key2List)
> {
> //key2の値がkeyと等しいものを抽出
> var aList = (from a in listA
> where a.key2 == key
> orderby a.key1 ascending
> select a);
> foreach (var al in aList)
> {
> //listBのkey2がalのkey2と等しいかつlistBのtimeがalのtime以降のもので
> //最も日付が古いものを抽出
> var result = (from b in listB
> where al.time <= b.time && al.key1 == b.key1
> orderby b.time ascending
> select new { al.key2, b.key1, b.item, b.time }).FirstOrDefault();
> if (result != null)
> {
> Console.WriteLine(result.key2.Replace("-", "") + "," + result.key1 + "," + result.item + "," + result.time);
> }
> }
> }
>

朱鷺さん

ありがとうございます。
早速、置き換えて確認してみます。

引用返信 編集キー/
■78647 / inTopicNo.14)  Re[10]: C#での繰り返し文
□投稿者/ D (7回)-(2016/02/01(Mon) 09:23:38)
D さんの Web サイト
No78645 (WebSurfer さん) に返信
> ■No78627 (D さん) に返信
>
> 先にお願いしましたけど、
>
>>ここに直リンを張りますね。
>>http://s1.gazo.cc/up/174076.png
>
> そのテーブルをベースにどういうことをしたいか説明していただけませんか。
>
> 掲示板に書いてあること以外何も知り得ない第三者にわかる言葉で書いてくださいね。

WbSurferさん

すみませんでした、掲示板で質問をするのがはじめてなもので、書き方がよくありませんでした。
初心者の私にご指導いただきありがとうございました。
引用返信 編集キー/
■78648 / inTopicNo.15)  Re[11]: C#での繰り返し文
□投稿者/ WebSurfer (805回)-(2016/02/01(Mon) 12:21:28)
No78647 (D さん) に返信

> すみませんでした、掲示板で質問をするのがはじめてなもので、書き方がよくありませんでした。

話が通じてますでしょうか?

回答者が質問者さんのやりたいことを想像しなくて済むように、コードや結果ではな
く言葉で要件を明確に書いて欲しいということなんですが・・・

例えば、先のレスで私が質問者さんのやりたいことを、

> (1) テーブル A と B で key1 が同じ、
> (2) テーブル A と B で time が B の方が遅いか同じ、
> (3) テーブル A で key2 が "A-1"

と想像しましたが、そのように条件を書いてほしいということです。

朱鷺さんが、上の条件に「最も日付が古いもの」という条件を加えていますが、それは多
分質問者さんが示した結果から想像されてのことだと思います。

でも、質問者さんはその条件を書いてないので、想像の域を超えていません(その想像は
多分合っていると思いますが)。

想像が間違っていたり、他にも条件があるとすると、回答は質問者さんの求めるものには
なりません。

なので、きちんとやりたいことを書く必要があるのです。

引用返信 編集キー/
■78650 / inTopicNo.16)  Re[12]: C#での繰り返し文
□投稿者/ WebSurfer (806回)-(2016/02/01(Mon) 14:07:36)
質問者さんは去ってしまわれたような気がしますが、このまま中途で終わっても何ですので、
自分が質問者さんのレスから最初に想像した条件 (1) 〜 (3) に以下のように (4) の条件
(多分、朱鷺さんの考えと同じ)を追加した場合のコードをアップしておきます。

(1) テーブル A と B で key1 が同じ、
(2) テーブル A と B で time が B の方が遅いか同じ、
(3) テーブル A で key2 が "A-1"、
(4) 上記 (1) 〜 (3) の結果、key1 が同じレコードが複数ある場合は B.time が最も古いもののみ取得。

下のコードでコメントの「// B の各グループの中で time が最小の B を抽出」以下がそれです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleAppLinq2
{
    public class A
    {
        public string key1 { get; set; }
        public string key2 { get; set; }
        public DateTime time { get; set; }
    }

    public class B
    {
        public string key1 { get; set; }
        public string item { get; set; }
        public DateTime time { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            List<A> listA = new List<A> {
                new A { key1 = "A", key2 = "A-1", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "A", key2 = "A-2", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "A", key2 = "A-3", time = DateTime.Parse("2016/1/1") },
                new A { key1 = "B", key2 = "A-1", time = DateTime.Parse("2016/1/11") },
                new A { key1 = "B", key2 = "A-2", time = DateTime.Parse("2016/1/16") },
                new A { key1 = "C", key2 = "A-1", time = DateTime.Parse("2016/1/21") }
            };

            List<B> listB = new List<B> {
                new B { key1 = "A", item = "あ", time = DateTime.Parse("2016/1/4") },
                new B { key1 = "A", item = "い", time = DateTime.Parse("2016/1/14") },
                new B { key1 = "A", item = "う", time = DateTime.Parse("2016/1/24") },
                new B { key1 = "B", item = "え", time = DateTime.Parse("2016/1/5") },
                new B { key1 = "B", item = "お", time = DateTime.Parse("2016/1/15") },
                new B { key1 = "B", item = "か", time = DateTime.Parse("2016/1/25") },
                new B { key1 = "C", item = "き", time = DateTime.Parse("2016/1/6") },
                new B { key1 = "C", item = "く", time = DateTime.Parse("2016/1/16") },
                new B { key1 = "C", item = "け", time = DateTime.Parse("2016/1/26") }
            };
            
            // 最初の想像と同じ条件で抽出
            var result = from b in listB
                         join a in listA
                         on b.key1 equals a.key1
                         where b.time >= a.time && a.key2 == "A-1"
                         select new { Akey2 = a.key2, Bkey1 = b.key1, Bitem = b.item, Btime = b.time };

            foreach (var x in result)
            {
                Console.WriteLine("A.key2={0}, B.key1={1}, B.item={2}, B.time={3}", x.Akey2, x.Bkey1, x.Bitem, x.Btime);
            }

            /*
            結果は同じく:
            A.key2=A-1, B.key1=A, B.item=あ, B.time=2016/01/04 0:00:00
            A.key2=A-1, B.key1=A, B.item=い, B.time=2016/01/14 0:00:00
            A.key2=A-1, B.key1=A, B.item=う, B.time=2016/01/24 0:00:00
            A.key2=A-1, B.key1=B, B.item=お, B.time=2016/01/15 0:00:00
            A.key2=A-1, B.key1=B, B.item=か, B.time=2016/01/25 0:00:00
            A.key2=A-1, B.key1=C, B.item=け, B.time=2016/01/26 0:00:00
            */

            // B の key1 でグループ化してみる
            var result2 = from b in listB
                          join a in listA
                          on b.key1 equals a.key1
                          where b.time >= a.time && a.key2 == "A-1"
                          group b by b.key1 into newGroup
                          select newGroup;

            foreach (var key1Group in result2)
            {
                Console.WriteLine("Key: {0}", key1Group.Key);
                foreach (var b in key1Group)
                {
                    Console.WriteLine("\t{0}, {1}", b.item, b.time);
                }
            }

            /*
            結果は:
            Key: A
                あ, 2016/01/04 0:00:00
                い, 2016/01/14 0:00:00
                う, 2016/01/24 0:00:00
            Key: B
                お, 2016/01/15 0:00:00
                か, 2016/01/25 0:00:00
            Key: C
                け, 2016/01/26 0:00:00
            */

            // B の各グループの中で time が最小の B を抽出
            var result3 = from b in listB
                          join a in listA
                          on b.key1 equals a.key1
                          where b.time >= a.time && a.key2 == "A-1"
                          group b by b.key1 into newGroup
                          from c in newGroup
                          where c.time == newGroup.Min(x => x.time)
                          select c;

            foreach (var x in result3)
            {
                Console.WriteLine("B.key1={0}, B.item={1}, B.time={2}", x.key1, x.item, x.time);
            }

            /*
            結果は:
            B.key1=A, B.item=あ, B.time=2016/01/04 0:00:00
            B.key1=B, B.item=お, B.time=2016/01/15 0:00:00
            B.key1=C, B.item=け, B.time=2016/01/26 0:00:00
            */
        }
    }    
}

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -