【VB.NET】LINQ友の会【C#, C♯, C#】

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん
垢版 |
2008/02/09(土) 23:51:34
VisualStudio2008より追加された便利で強力な機能

  統合言語クエリ (LINQ : Language Integrated Query)

ちょっと使ってみると、意外と難しいし、テクニック的にも奥が深いものです。
関数型言語にしかないような機能ラムダ式(Lambda式)などはオブジェクト指向とは一味違う機能です。
DataBaseの操作にも、Xmlの操作にも、さらにもっと単純な配列なコンテナにさえ機能する
言語共通・高汎用な統合言語クエリを皆で一緒にマターリ勉強しましょう。
質問、便利なマイテクニックの発表、いろいろやっちゃってください。
2008/02/16(土) 19:15:04
あと、同値分類みたいなのは、group by じゃだめ?
6058
垢版 |
2008/02/16(土) 19:24:17
>>53
パターンマッチっぽくしてみたよ。

var table1 =
from row1 in tableOrg1
let 評価結果 = tableOrg2.Where(row2 => row2.以上 <= row1.得点 && row1.得点 < row2.未満)
                .Select(row2 => row2.評価)
                .Concat(Enumerable.Repeat("見つからないよ", 1))
                .Take(1)
from 評価 in 評価結果
select new { row1.氏名, 評価 };
2008/02/16(土) 20:13:38
>>1です

>>57
概念を導入することと、どう表現してどう使わせるかは違うと思うんですよ
高度な概念も、図にしてみれば、あんたバカ、何当り前の事をと思わずにはいられない概念は多いと思うんですよ。
圏論のそんな物の内の一つだと思っています。
ちなみにヘジたん理論無視の直感実装大好きです、実装は理屈じゃないですよ、いいと思ったらそれがいいんだと思ってます。
理屈は後付け、原爆の爆縮レンズが開発される時に、火薬職人が二種類の火薬使えばいいじゃんといって、頭でっかちのノイマンが計算するっていうのは悪くないと
ここでは、火薬職人がヘジたんで、頭でっかちがリサーチの人たちですね。

>>60
ありがとさんです、なるほどなるほど、いろいろ参考になりますです。
まだまだ初心者なんで今後ともよろしくお願いします。
2008/02/16(土) 20:26:54
高度な概念といえば、たとえばλ式なんかがそうなんですが、関数だと思うと恐ろしい事になりますが、
あれってとどのつまりは、引数が添え字になっている唯のベクトルですよね。なにやら要素が並んでいるだけの物です。
よく無限次元になってしまうので、普通に書けないからああ書いたというだけで……
もっと解り易くならないかなと思ったりします。
2008/02/16(土) 21:07:54
DB屋もやってる俺からみると、これはぶっちゃけキモい
変にSQLの知識あるとちょっと慣れそうにないなぁ、これは
2008/02/17(日) 00:29:39
>>63
俺も一応オラクルマスター持ちなんだが(システム屋から足を洗って長いけど)、
それはそれ、これはこれだな。
DBとだけ使っている限りは、SQL以上のことができるわけじゃないから「ただのキモいSQL」という見方も、そう間違ってはいないだろう。
SQLを基準にして見れば、SQLとの違いが気持ち悪いのは確か。しかし、メモリ上のデータのグループ化やら結合やら、定型的なわりに再利用しづらいコードを
いちいち書いては「こんな処理、SQLならSELECT文一発なのに」と思っていた人にとっては、むしろSQLに近づいた感じなのではないだろうか。
2008/02/17(日) 00:53:13
OOP 言語が SQL に近づいたこと
(より「意図通りに書ける」ようになった)も重要だし、
in-memory オブジェクト、XML、DB に対して
ほぼ同じ書式でクエリが書けることも重要かと。
2008/02/17(日) 20:41:50
LINQとSQLの違いのひとつにプランナの有無がある。
LINQは処理順に書かなくてはならないし、必ず記述順で処理される。
LINQはSQLの類似品と考えるより、
Enumeratorやコールバック(ラムダ)を使ったパイプライン処理であり
コレクション処理の延長だと思ったほうが誤解がない。
2008/02/17(日) 21:31:55
>>63-66
いずれ統一化できる下準備になるのではないかと思っています。
最終的には、コンパイル済みの.NETのコードを直接 DB に送り込み、DBがそれを直接解釈するという形になるのではと想像しています。
そうしますと、C#/VB.NETで書かれたSQLとDBのSQLの微妙な解釈の違いが完全になくなると思うので、これは安心できると思うのですがどうでしょう?
あと、コンパイル済バイトコードを送りつけるなら、DBのスピードもあがるかもとかとか・・・
また、セキュリティーの関係ではSQLインジェクションの類は完封できそうです。

>>1 です、今日は、表の分割、行の分類のやり方を紹介します。
2008/02/17(日) 21:32:46
Q.表を分割したい
 LINQの文法は、例えば以下のような形式になっています。
 from アイテム名 in 元データ where アイテム名.項目=="条件のあっているデータ" select 新しい行の定義
 上記の文の最後の部分「select 新しい行の定義」の部分を「group 新しい行の定義 by ふるい分けの基準となる値」
 とする事により表を分割できます。
 
 ここでは
  1 "ABC"
  2 "DEF"
  3 "ABC"
  4 "DEF"
  5 "GHI"
 となっている表を、以下の三つの表に分割する方法です。
ABC のある列
 1 ABC
 3 ABC
DEF のある列
 2 DEF
 4 DEF
GHI のある列
 5 GHI
2008/02/17(日) 21:33:19
 ツールボックスから DataGridView と TextBox を三つ貼り付けて以下のコードを実行すると三つの表が完成します。
 var tableOrg1 = new[] {
  new { LineNo = 1 , Data = "ABC" } ,
  new { LineNo = 2 , Data = "DEF" } ,
  new { LineNo = 3 , Data = "ABC" } ,
  new { LineNo = 4 , Data = "DEF" } ,
  new { LineNo = 5 , Data = "GHI" } ,
 };
 var dataGridViewArray = new[] { dataGridView1, dataGridView2, dataGridView3 };
 var textBoxArray = new[] { textBox1, textBox2, textBox3 };
 var tableArray = (from row in tableOrg1 group row by row.Data).ToArray();
 for (int i = 0; i < dataGridViewArray.GetLength(0) && i < tableArray.GetLength(0); ++i) {
  dataGridViewArray[i].DataSource = tableArray[i].ToArray();
  textBoxArray[i].Text = tableArray[i].Key.ToString();
 }
by row.Data の部分を変更することにより、例えばby row.Data.Length などとする事により複雑なふるい分けが可能です。
2008/02/17(日) 21:34:14
Q.特定項目で分類したい
 項目に大小比較ができれば、ソートしてしまえば良いのですが、それが無い場合には少し困った事になります。
 ここでは、前出の「表を分割したい」と組み合わせた方法を紹介します。
 それは、前出のLINQ文「from row in tableOrg1 group row by row.Data」の後ろに「into tmp1 from tmp2 in tmp1 select tmp2」を追加して
 from row in tableOrg1 group row by row.Data into tmp1 from tmp2 in tmp1 select tmp2
 とすると実現できます、まじないの部類ですが・・・うまく行きます。

 var tableOrg1 = new[] {
  new { LineNo = 1 , Data = "ABC" } ,
  new { LineNo = 2 , Data = "DEF" } ,
  new { LineNo = 3 , Data = "ABC" } ,
  new { LineNo = 4 , Data = "DEF" } ,
  new { LineNo = 5 , Data = "GHI" } ,
 };
 var table1 = from row in tableOrg1 group row by row.Data into tmp1 from tmp2 in tmp1 select tmp2;
 dataGridView1.DataSource = table1.ToArray();
71デフォルトの名無しさん
垢版 |
2008/02/17(日) 21:35:03
linq の文法 query-body ::= query-body-clause* final-query-clause query-continuation?
この query-body-clause* の部分が複数になると急に難解になりますね。
どういう時に、使うと見通しが良くなるのか、あるいはどういう時にろくな事にならないのか
パターンとアンチパターンを揃える必要がある気がします。
2008/02/17(日) 21:40:18
>>71
>この query-body-clause* の部分が複数になると急に難解になりますね。

とりあえず改行とインデントとletで工夫かな。
2008/02/18(月) 18:11:36
>>1 です、今日は、LINQ文法の詳細をやろうと思ったのですが……

一通りざらっと見てみて、LINQの文法はひょっとして質が悪いのでは?という疑惑が湧いてきました。
LINQの核心部分は、from join その他 LINQ キーワードではなく、実際の処理が記述されている System.Linq.Enumerable であるので
これが致命傷になるとは思えないのですが、簡単に使うための上っ面としては今一な気がします。
このキーワードと文法には、変な汎用性があり、相当な広範囲にわたって複雑な処理が可能ですが
それを行うなら、メソッドベースで行ったほうが良さそうな気がします。

1.方向性としては、良くある定型について、LINQ 文法を使って完結に記述。使用例一覧に纏めておき、サクッと使う。
2.例外的なクエリについては、メソッドを使い、一つ一つ区切りながらクエリを完成させる。

こういう使い方が良いのではと思い始めました。
皆さんはどんな意見をお持ちでしょうか?
74デフォルトの名無しさん
垢版 |
2008/02/18(月) 18:13:51
http://www.microsoft.com/japan/msdn/net/bb308959.aspx より。
今日はこれを、初心者向けの説明にしようと思ったのですが……難しすぎ
区切り無く、際限なく、限りなく書き方が広がるとマニュアル化ができません。
query-continuation? の定義に query-body があるのが最悪だ。
だれがこれを手際よく解説するアイディアお持ちで無いでしょうか?

query-body ::= query-body-clause* final-query-clause query-continuation?
query-body-clause ::= (from-clause | join-clause | let-clause | where-clause | orderby-clause)
join-clause ::= join itemName in srcExpr on keyExpr equals keyExpr (into itemName)?
let-clause ::= let itemName = selExpr
where-clause ::= where predExpr
orderby-clause ::= orderby (keyExpr (ascending | descending)?)*
final-query-clause ::= (select-clause | groupby-clause)
select-clause ::= select selExpr
groupby-clause ::= group selExpr by keyExpr
query-continuation ::= into itemName query-body

#ひょっとしてカンマ忘れてる?
#orderby-clause ::= orderby (keyExpr (ascending | descending)? ,)*
2008/02/18(月) 18:52:44
>>73
LINQ って言葉の指す範囲は広くて、クエリ式もメソッド形式もどっちも LINQ よ。
from x in list みたいなのはクエリ式。

クエリ式でないと書きづらいのは、多重 from と join と let くらいかな。
まあ、transparent な変数が絡むとクエリ式使わないときつい。
逆に、クエリ式で書けないことも実に多い。

まあ、個人的には、
クエリ式で書けるものは全部クエリ式で、
それ以外だけメソッド形式で書いてる。
2008/02/18(月) 18:56:38
>>74
俺は
基本的に、select と group by は最後に来る。
その後ろにさらにクエリを続けたい場合は into x を置いてからさらに続ける。
と説明してる。
2008/02/18(月) 19:00:39
対応関係としては、

from x in list where x > 0 select x;

list.Where(x => x > 0); // 最後の Select はきえる

from x in list select x * x;

list.Select(x => x * x);

from x in list select x * x into y where y > 5 select y;

list.Select(x => x * x).Where(y => y > 5); // .Select の後ろにさらにメソッドが続く
2008/02/20(水) 00:08:01
>>1
お前社員だろwwwwwww
こんなの広めてどうするwwwwww
2008/02/20(水) 04:36:32
Hibernate とは違うの?
2008/02/20(水) 10:09:28
>>79
後出しじゃんけんの分強い
対象が Java か .NET か
LINQ では、C# や VB の言語仕様もいじったから書きやすい
2008/02/20(水) 18:48:34
>>1です、一週間では見えてくるものが少ないですね、暫く使い込んでみることにしました。
Linq to SQL , Linq to XML , 生Linq と全部使い込みをしないと見えてきにくいですね。

>>78
おれ社員じゃないよ、ボーランド大好きヘジたん信者の可能性は高いけど(笑
それと食わず嫌いはどうかなwwww
問題もそれなりに多そうだなというのも見えてきましたけど開発効率めちゃくちゃ高いよぉ。
2008/02/20(水) 20:25:54
>>79
簡単に言うと、O/Rマッピングは対症療法、LINQは原因療法、みたいな。
なんでこんなのが必要かってのは、
ttp://d.hatena.ne.jp/fromdusktildawn/20060216/1140064918
を読むと理解が深まるかも。
2008/02/20(水) 21:16:01
LINQ最大の効果ポイントは、一般化と高速化にあるんじゃないかな
データベースから、XMLから、果ては適当なクラスや構造体まで統一手法で操作可能という点。
O/Rマッピングと目指すところがそもそも違うと思う
2008/02/20(水) 22:14:52
キャッシュポリシーは単純だけど、Linq to SQLはORM。
これだけはほかのと系統が違う。これで使うラムダ式は特殊なもの。
2008/02/20(水) 23:37:59
( ゚д゚)ノ ハイ!シツモーン!です。
次のように追加してくと実行時間がリニアに増えてくんだけど何か間違えてるんでしょうか?
プロジェクトごとあげてみました。
http://www.borujoa.org/upload/source/upload16875.zip
class Program {
static void Main(string[] args) {
var db =new TestDB(@"testDB.sdf");
db.DeleteDatabase();
db.CreateDatabase();
var count=0;
var tu=new TickUtil();
tu.WriteLine("begin--");
while(count++<5000){
var person=new Person{Name=string.Format("name-{0:8d}",count),
Age=count,Explanation=string.Format("Explain-{0}",count)};
db.Persons.InsertOnSubmit(person);
db.SubmitChanges();
if(count%100==0)
tu.WriteLine("new person-count={0}",count);
}
tu.WriteLine("end-");
}
}
2008/02/21(木) 01:06:41
LINQでWin32のメッセージマップって書けないの?
2008/02/21(木) 01:43:02
C++/CLI には無いの?
2008/02/21(木) 07:12:47
>>85
遅くなるというのは1件あたりの処理時間が増えるということかな?
それだったらCompact Editonなのが影響してるのかもしれない。
2005Expressで実行してみたらどうだろう。

db.SubmitChanges(); は5000件まとめての方が速いと思う。
メモリがきついようなら500件くらいまとめてで。
2008/02/21(木) 08:46:06
>>88
百件のインサートごとにその間にかかった時間を書いてるんですが、それがリニアに増えてきます。
Express or Serverで試してみます。

実際の実行時はまとめたほうがよさげですね。
2008/02/21(木) 10:05:01
>>85のソースから
> protected string SetAndReturnDifferenceTimeString() {
> int current = Environment.TickCount;
> int lastDiff = current - _last;
> _last = current;
> return "[" + lastDiff + "]";
> }
> public void WriteLine(string message) {
> Console.WriteLine(message + " " + SetAndReturnDifferenceTimeString());
> }
> public void WriteLine(string message, params object[] args) {
> WriteLine(string.Format(message, args));
> }

100件毎に実行されるのってWriteLine(string message, params object[] args)じゃね?
最近プログラミングしてないんで間違ってたらスマソ
2008/02/21(木) 10:13:41
>>90
下のWriteLine()の中で上のを呼んでる。
2008/02/22(金) 00:11:14
>>1 です
クエリ式はとりあえず放って置いて、メソッドでしか表現できないタイプのものを解説してみようと思っているのですが
まずは一発目で Aggregate あたりからやってみようかと思ってます。
ただ、このメソッドあまりにも関数型言語らしい仕様をしています。
何か良い説明方法はないかと色々さがしているのですが、良いのがあったら誰か紹介してください。
http://d.hatena.ne.jp/blanketsky/20071129/1196329379
とりあえず、この辺りとか見てみたのですが……
こんなの見せられたら初心者さん気絶するよなとか思いつつ、何かいいのはないかなと……
2008/02/22(金) 00:32:05
>>92
forループからの置き換えで解釈してみては。

int sum = 0;
for (int i = 1; i <= 100; i++) {
  sum += i;
}

これをAggregateで記述するとどうなるか、とか。
9485
垢版 |
2008/02/22(金) 00:39:59
Comapctでまとめて実行するようにしたらリニアに増加するのはなくなった様。
10000件ぐらいまではまとめたほうがトータルの実行時間が短くなった。
もっと多くした場合はどうなるかは今度試します。
ほかのデータベース試してないけれど、なんかCompactのせいっぽい匂いが・・・
2008/02/22(金) 01:20:37
>>92
その情熱がどこから来るのかわからんが、Aggregateなら
・sum、factあたりを通常の再帰関数で書く
・共通する部分を抜き出す
・これがAggregateです
っていうのがわかりやすいんじゃないの?
2008/02/22(金) 11:23:52
>>92
http://ufcpp.net/study/csharp/sp3_stdqueryo.html#aggregate
2008/02/22(金) 19:46:15
クエリ式はきもいけどLINQ自体はないと生きていけんよ
コレクションに対するアルゴリズムは絶対に必要だ
XMLやSQLは別になくても生きていけるとは思うが
98デフォルトの名無しさん
垢版 |
2008/02/22(金) 22:13:52
>>92
2008/02/23(土) 01:08:33
>>1 です
>>93 結局ループをどの様に書くかという問題なのだからそれが一番いいような気がしました。
それと、これは群論の本(数学の本です)を読んでいて、抽象化は具体例を限りなく沢山作ってその中から共通の物を取り出すことだという記述があって
それも考慮にいれて、まず具体例、それからループへと展開する方針でいってみようと思います。

>>95
申し訳ないですが、再帰は最終手段だと思います、非常に良くないと思います。それ以外の部分は賛成です。
再帰とラムダ(or Delegate)は絶対に最初に記述して説明してはならないものだと確信しています。

>>96
>http://ufcpp.net/study/csharp/introduction.html
>実を言うと、僕は趣味でプログラミングをしてるだけで、 C# は研究とは一切関係なかったりします。
>(むしろ C/C++ を使うことが多かった。 2007年追記: 最近では割となんでも C# で書くようになりました。)
>初めて C# について調べてみたとき(ちょうど Java に物足りなさを感じ、SUNの方針に憤りを感じていたころです)、
> C# が普及してくれればプログラミングにかかる手間は大幅に削減されると感じるました。
>しかし、Microsoft は順調に行かなさそうなものはばっさりと切り捨てることで有名な企業ですし、
>世間の C# への関心が低ければ、C# は普及することなく消え去ってしまうでしょう。
>そこで、少しでも早く C# が普及するようにとの願いを込めて当コンテンツを作成することにしました。
実は自分も全く同じ境遇です、でも研究者じゃありません、ただのプログラマですが……
関数型言語をやっていて思うところで、こんなの一発なのにというコードがオブジェクト指向のスタイルでは全くまともにかけなくて歯がゆい思いをしていました。

今日からお休みなので、これから練ってみます、明後日辺りから書き始めるかもしれません。
2008/02/23(土) 01:09:33
しかし、http://msdn2.microsoft.com/ja-jp/library/bb549218.aspx
これをみて理解できる人間が一体何人いるんだろうか……

Aggregate<(Of <(TSource, TAccumulate>)>)(IEnumerable<(Of <(TSource>)>), TAccumulate, Func<(Of <(TAccumulate, TSource, TAccumulate>)>))
この表現からぱっと見た目に使い方がわかる人は一体何人いるんだろうと、首を傾げそうになります。
ドキュメントのつくりを一度見直すべきだと思う……強力なのに……

>世間の C# への関心が低ければ、C# は普及することなく消え去ってしまうでしょう。
こんな状態になって欲しくないです
これを使えば、エクセルで小計等をやるような操作を一行で書き下せますが、使える人が居なくなってしまう。
2008/02/23(土) 01:22:13
C++にBoostその他の取り合わせなんか、正にそんな世間の関心が低い状態。
LINQもそういうことになってしまうのは嫌だな。
2008/02/23(土) 02:31:52
一応世間に知られてからもう大分経つでしょ・・・
これ流行らないよ・・・
from の位置とか外人さんでも気持ちわるいんじゃないかな
10395
垢版 |
2008/02/23(土) 02:36:28
>>99
あー、ごめん、関数型言語とごっちゃになってた。
C#なら95の最初の手順を
・sum、factあたりを通常の関数で書く
でいいな。確かに再帰とかいらない。

蛇足ですが、あなたの対象とする「初心者」像がいまいちわからないのが
少し気になります。
2008/02/23(土) 03:22:34
>>102
発売後15日にして大分経っていたのか、それはショックだw
ごみレスつけるな、よそ行けよ
2008/02/23(土) 10:15:51
Selectが X->Y のマップになってるのはちょっと名前がわかり辛くて見つけられなかったな
duck typing(?)とかいう手法で Map :: X[] -> (X -> Y) -> Y[] を作っちゃった

拡張性も結構あるしガクジュツ的ではなくちゃんと実務に沿って開発しやすくなるような言語拡張だからLINQは流行ると思う
2008/02/23(土) 13:41:16
Enumerable.ForEachがほしい
2008/02/23(土) 14:51:39
要望出してSP1に入れさせようぜ
2008/02/23(土) 14:52:38
>>106 自分で作りなはれ。自分は作った。
2008/02/23(土) 14:56:38
晒して
2008/02/23(土) 15:10:50
void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
 foreach(T item in source) action(item);
}
ただこれだけのことだけど
こんなことしちゃうとコード全体がガラッと変わるから非公式にやるのは抵抗がある
2008/02/23(土) 15:17:25
なんでもかんでも一行でやろうとするのはC#的じゃないだろ
foreachぐらい分けて書こうぜ
2008/02/23(土) 15:42:04
http://www.microsoft.com/japan/msdn/net/bb394939.aspx

ヘジ自ら書いてる
これが俺のバイブル
2008/02/23(土) 16:44:36
foreachのみで簡潔に書けるものはforeachのみで良いと思います

foreach( var row in table ) 文 ;

これ以上何かをする必要はないだろうと思う、逆にややこしいだけだし。

はなしは変わって、http://ufcpp.net/study/csharp/sp3_stdqueryo.html#aggregate によると
> でも、メソッド提供だけでは、 join や let などがどうしてもきれいに表現できなかったので、
<やむなく SQL 風のクエリ式を導入したそうです。
>(プログラミング言語の中に別に言語を埋め込むというのはデメリットも大きくて、
>言語制作者にとっては結構ためらわれる行為。)
>(join や let をきれいに書くためには、どうしても透過識別子のような考え方が必要だった。)
という事らしいのですが、私は、むしろ逆で、これを見た瞬間λ式消滅、これは素晴らしい!!
と思ったものなんですが……
"Language Integrated" Query というぐらいですから、最初こちらがあったのだと想像していのですが逆だったんですね。
foreach にはλ式は登場しないので十分だと思っています。
2008/02/23(土) 16:47:27
デザイナを使っているとdelegateやeventなんて全然意識しやいじゃないですか
ダブルクリックすれば勝手にコード登場となって、こういうややこしいものは後回しにして使い方を最初に知ることができる。
これがC#の良い点だと思うんですよ。
2008/02/23(土) 16:50:49
List<T>やArrayにはForEachがあるだろ
匿名メソッドよりも,普通のメソッドを直接渡すときに気持ちいいんだよね
list.ForEach(Console.WriteLine);みたいに
初めてみたときはびっくりしたけど
2008/02/23(土) 16:59:23
普通にプログラミングしててもSelectやWhereは腐る程出てきて
それらを書くぶんにはクエリ式でなく拡張メソッド+ラムダ式の方がシンプルに書ける
ラムダ式は他にもプログラミングのあらゆる局面で使うと便利なことが多い
対してクエリ式はSelectManyやJoinなんかで使うとシンプルに書けるけど
そんなん滅多に使わん
2008/02/23(土) 17:43:25
遅延評価のせいで,一旦必要な部分を評価しないといけないのか・・・

new[] { 1, 2, 3, 4, 5 }.Select(
    x => {
        Console.WriteLine(x);
        return x;
    }
).ToArray();
2008/02/23(土) 18:06:36
遅延評価の問題すっかり忘れてた、あんまり意識する必要無いとおもったけど、デバッグ時にも面倒が起りますね。
あなたがその値を見るまでは値は計算されていませんって、まるでシュレディンガーの猫のような現象がありました。
2008/02/23(土) 18:24:47
普通に書いたらええがな
2008/02/23(土) 18:29:18
.ToList().ForEach(Console.WriteLine) でいいじゃん
2008/02/23(土) 18:30:33
ToList超きもい
2008/02/23(土) 18:32:42
遅延評価はLINQだと実態があいまいになりがちだがHaskellを使うと、なんというかテツガクしたくなる。
ものすごく面白いが、万人にお勧めではない。
2008/02/23(土) 18:35:44
IEnumerable<>でforeachするときの例っぽいの書こうとした^p^
2008/02/27(水) 19:00:07
>>1 です
 ちょっとスタイル変更、くだすれC#だと、配列よりも List クラスの方が需要ありそうだったので。
 実際、実用上は配列って事はありえない気がしますし。
 名前は全部漢字にして、型名には末尾に"型" と付けてみました。
2008/02/27(水) 19:00:49
Q.売上表で小計をもとめるような計算をしたい(1)
 Aggregate が便利です。
 以下の例では、合計原価と合計売価を求めます。解りやすさ優先で、型をすべて書ききったバージョンです。

 System.Collections.Generic.List<売上帳の行型> 売上帳 = new System.Collections.Generic.List<売上帳の行型>();
 売上帳.Add(new 売上帳の行型() { 品名 = "デスクトップPC", 数量 = 1, 原価 = 100000, 売価 = 120000 });
 売上帳.Add(new 売上帳の行型() { 品名 = "ノートPC", 数量 = 2, 原価 = 250000, 売価 = 280000 });
 // お試し表示
 dataGridView1.DataSource = 売上帳;
 // 合計の計算方法
 合計型 合計の初期値 = new 合計型() { 合計原価 = 0, 合計売価 = 0 };
 合計型 合計表 = 売上帳.Aggregate(
  合計の初期値,
  (合計型 直前の合計, 売上帳の行型 行) => new 合計型() { 合計原価 = 直前の合計.合計原価 + 行.数量 * 行.原価, 合計売価 = 直前の合計.合計売価 + 行.数量 * 行.売価 }
  );
 dataGridView2.DataSource = new 合計型[] { 合計表 };

 public class 売上帳の行型 {
  public string 品名 { get; set; }
  public int 数量 { get; set; }
  public int 原価 { get; set; }
  public int 売価 { get; set; }
 }
 public struct 合計型 {
  public int 合計原価 { get; set; }
  public int 合計売価 { get; set; }
 }
2008/02/27(水) 19:01:50
>>125の続き 売上表で小計をもとめるような計算をしたい(2)
省けそうな型名は省略したバージョンです

var 売上帳 = new System.Collections.Generic.List<売上帳の行型>();
売上帳.Add(new 売上帳の行型() { 品名 = "デスクトップPC", 数量 = 1, 原価 = 100000, 売価 = 120000 });
売上帳.Add(new 売上帳の行型() { 品名 = "ノートPC", 数量 = 2, 原価 = 250000, 売価 = 280000 });
// お試し表示
dataGridView1.DataSource = 売上帳;
// 合計の計算方法
var 合計表 = 売上帳.Aggregate(
 new { 合計原価 = 0, 合計売価 = 0 },
 (直前の合計, 行) => new { 合計原価 = 直前の合計.合計原価 + 行.数量 * 行.原価, 合計売価 = 直前の合計.合計売価 + 行.数量 * 行.売価 }
 );
dataGridView2.DataSource = new[] { 合計表 };
2008/02/27(水) 19:03:01
>>126の続き 売上表で小計をもとめるような計算をしたい(3)
上記のコードが何をしているのかといいますと、以下のコードのような処理をしています。

var 売上帳 = new System.Collections.Generic.List<売上帳の行型>();
売上帳.Add(new 売上帳の行型() { 品名 = "デスクトップPC", 数量 = 1, 原価 = 100000, 売価 = 120000 });
売上帳.Add(new 売上帳の行型() { 品名 = "ノートPC", 数量 = 2, 原価 = 250000, 売価 = 280000 });
// お試し表示
dataGridView1.DataSource = 売上帳;
// 合計の計算方法
var 直前の合計 = new { 合計原価 = 0, 合計売価 = 0 };
foreach (売上帳の行型 行 in 売上帳)
{
 直前の合計 = new { 合計原価 = 直前の合計.合計原価 + 行.数量 * 行.原価, 合計売価 = 直前の合計.合計売価 + 行.数量 * 行.売価 };
}
dataGridView2.DataSource = new[] { 直前の合計 };
2008/02/27(水) 19:04:24
>>127の続き 売上表で小計をもとめるような計算をしたい(4)
これを使うと簡単になるケース
合計型と売上帳の行型が同じなら、コードは単純になります

var 売上帳 = new System.Collections.Generic.List<売上帳の行型>();
売上帳.Add(new 売上帳の行型() { 品名 = "デスクトップPC", 数量 = 1, 原価 = 100000, 売価 = 120000 });
売上帳.Add(new 売上帳の行型() { 品名 = "ノートPC", 数量 = 2, 原価 = 250000, 売価 = 280000 });
// 合計の計算
var 合計行 = 売上帳.Aggregate((直前の合計, 現在の行) => new 売上帳の行型() { 原価 = 直前の合計.原価 + 現在の行.数量 * 現在の行.原価, 売価 = 直前の合計.売価 + 現在の行.数量 * 現在の行.売価, 品名 = "合計" });
売上帳.Add(合計行);
// お試し表示
dataGridView1.DataSource = 売上帳;
129デフォルトの名無しさん
垢版 |
2008/02/27(水) 19:05:23
まとめ
駄目だ、どうあがいても単純になりません。
3 番目を書いてみたら、foreach で書いたほうが見通しがよさそうな感じすらしてきます。
綺麗になるのは、アキュムレーターの型とコンテナ要素の型が一致しているとき
もしくはアキュムレーターの型が int のような単純型で有る場合に限られます。
メソッド方式にはやはり何かが足りない感じがします。
LINQの新規キーワードとして、それも foreach をイメージできるような構文にして
"aggregate 売上帳" と書いたら、型名、その他をインテリセンスがズバズバッと書き出して、
作る側は中身をを書くだけといった具合になれば使えそうな気がするのですが……
もしくは Excel の、式のコピーのようなイメージができれば、やる事は一番上の式を書く事となるのですが。
2008/02/28(木) 02:02:30
ところでこのコードってVB?
2008/02/28(木) 11:52:14
驚くべきことに今まで一行もVBのコードは出てきていないんだ
2008/02/28(木) 12:47:55
ほいじゃVB版Linq for XML
XMLリテラルが売りですのじゃ
Dim xm = <AAA>
  <BBB id="1">aaaaacxzc</BBB>
  <BBB id="2">aaaaaxczx</BBB>
  <BBB id="3">aaaaaxcxz</BBB>
  <BBB id="4">aaaaaxczx</BBB>
  <BBB id="5">aaaaaxxxx</BBB>
  <BBB id="6">aaaaazzzz</BBB>
  <BBB id="7">aaaaacccc</BBB>
  <BBB id="5">aaaaaxxxx</BBB>
  <BBB id="6">aaaaazzzz</BBB>
  <BBB id="7">aaaaacccc</BBB>
</AAA>
Dim rs = From x In xm...<BBB> _
  Where x.@id > 2 _
  Distinct Skip 1 Take 3 _
  Order By x.@id Descending _
  Select ID = x.@id, x
For Each r In rs
  Console.WriteLine(r)
Next
2008/02/28(木) 13:15:08
クエリ式はC#よりVBの方が馴染んでるよなあ
VBのラムダ式は糞だけど
2008/02/28(木) 17:54:04
>>129
AggregateはSumやMaxと同じで集合関数として使うように設計されてるので
group by と組み合わせて使うのが普通なのだと思う。
この例だとSumが使えるのだがAggregateを使ってみた。
var 合計表 = (
  from uri in 売上帳
  group uri by 1 into g
  select new 合計型(){
     合計原価 = g.Sum(o => o.原価 * o.数量),
     合計売価 = g.Aggregate(0, (t,o) => t + o.売価 * o.数量)
  }).First();
Console.WriteLine("{0}, {1}", 合計表.合計原価, 合計表.合計売価);
2008/03/07(金) 01:17:17
C#なんだから大概の物は関数型チックにかくより普通に書いた方が
見やすいのは当たり前
2008/03/07(金) 11:55:15
Expression Treeってフィールドの値を変更できないのか
できたらおかしいのはわかるけどDynamicMethodの簡易版として使うには貧弱だな
2008/03/07(金) 12:01:30
>>136
そういう用途だと、LINQ の Expression から DLR の AST Expression に変換してしまうのがいいかも。
2008/03/07(金) 17:40:05
LINQってDataTableに対してグループ化をしてDataGridViewに表示したり出来るんですかね?
現在、DataTableに対してグループ化ってかなり無理矢理やらないと出来ないと思うんですが、
これができると、DataTableがかなり使いやすくなりそうです。
.NET3.5をインストールさせる動機になりそうなくらい・・・
2008/03/12(水) 12:24:53
みんな小難しいことばっかやってて、なんとなくLinq避けてたが、
実際に使ってみるとなかなかスイーツ(笑)な簡単さじゃないか。
List<T>なんか作って追加していって最後にToArray()してるようなのも
Linqで書き換えたら全部一行に出来そうだ。
2008/03/13(木) 01:52:23
あれ?出勤、昼だか夜だかわからなくね?
2008/03/13(木) 11:30:56
VB.NETもスレタイの仲間に入れてあげてください。
2008/03/13(木) 13:24:30
VB.NETは新機能が全く話題にならないよな
2008/03/13(木) 15:06:20
>>142
むしろ新機能はLINQ以外にあったっけか?
まぁ銀光とかあるけど
2008/03/13(木) 15:07:51
宣言時の型推論,ラムダ式とか?
2008/03/13(木) 15:16:04
Xmlリテラルとか。
2008/03/13(木) 15:18:19
C#2.0+C#3.0+αだな
2008/03/13(木) 16:24:25
ぶっちゃけXML生書き出来るようになったからって・・・
使う奴っている?

今一歩使い道が見つからん・・・
2008/03/13(木) 21:19:44
>Xmlリテラル

タイミング良くっつーかこんな記事がでてるね。

.NETプログラマーにとって、XSLTは終焉なのか?
ttp://www.infoq.com/jp/news/2008/03/XML-Literals

>XML Literalsは最初Haskell向けに開拓され、
>のちにMicrosoftにおいてC#で使用するために開発された。
>どちらの言語においてもうまく いかないことが判明したので、
>Visual Basicチームが飛び付いて、VB 9の礎石にした。

>これはそれほどまでに驚くことではない。
>というのもHaskell構文がVBScriptのインラインHTML表記の影響を
>もろに受けて いたからである。

まあヘジたんなら拒否るだろし、事実拒否ったんだろうなぁ。
2008/03/14(金) 22:40:14
テーブル値関数をLinq to SQLで利用しようとしてるんだけど、
実行したら、
ストアド プロシージャはクエリ内では使用できない。ってエラーになるんだよ。
これバグじゃないかな。
2008/03/15(土) 00:46:01
自己解決しました。ノシ
IsComposable=true がなかったのが原因みたいです。
なんだかなあ。
 
2008/04/06(日) 03:35:46
保守
152sage
垢版 |
2008/04/13(日) 01:33:35
LINQでのサブクエリの書き方が分からん。どう書くの?

SELECT
 A.KEY1, A.COL1, B.COL2
FROM
 (
  (SELECT * FROM TBL1) A
  INNER JOIN
  (SELECT * FROM TBL1) B
  ON B.KEY1 = A.KEY1
 )
2008/04/13(日) 02:32:31
そのままlinqに置き換えれば

var r =
 from i in
  (from a in TBL1
   from b in TBL2
   where a.KEY1 == b.KEY2
   select new { A = a , B = b })
 select new { KEY1 = i.A.KEY1 , COL1 = i.A.COL1 , COL2 = i.B.COL2 };

こんな感じだけど、この例だとサブクエリ必要なくね?
2008/04/13(日) 02:36:53
>>152
それ、LINQ だとサブクエリ要らない。

var q =
 from a in tbl1
 join b in tbl2 on a.Key equals b.Key
 select new { a.Key, a.Col1, b.Col2 };

サブクエリは普通に ↓ みたいに書ける。
from a in
 from b in list
 select b.SomeProperty
select a.SomeProperty
155デフォルトの名無しさん
垢版 |
2008/04/13(日) 14:50:18
そんなことしなくても
保守が容易な綺麗なコードを書けるから
(゚听)イラネ
2008/04/13(日) 16:44:19
最近LINQ初めて>>22見たんだけど、
コードが見通しよく整理されていく中盤からの展開は見てて痛快だなぁ
2008/04/24(木) 21:22:23
http://code.msdn.microsoft.com/vlinq
2008/04/24(木) 21:41:48
>>157
Visual LINQ Query Builder

VS2008用のアドインか
159デフォルトの名無しさん
垢版 |
2008/05/24(土) 20:45:08
Linqで書くと速くならないなら需要ないんじゃない
SQLでおなかいっぱいで
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況