「AKB49」が完結しましたね。始まったときはイロモノかと持ったのですが、なかなかどうして面白かったです。
あとはやっぱり「ベイビーステップ」がやっぱり楽しい。今回のような試合じゃないけど、テニスプレイヤーとしての一面を見せてくれるような回があるのがとてもよいです。
2016年1月20日水曜日
2016年1月18日月曜日
「真田丸」が面白い!
おぉ。いつの間にか年が明けておりますね…。ごにょごにょ…。
…さて、今年の大河ドラマ「真田丸」が面白いです!すごく!
大河ドラマはどうしても、最初のほうは、時代の背景や主人公の特に幼少期のエピソードなどの説明が主になってしまい、最初の二か月ぐらいは我慢してみてると、そのうち面白くなってくる。というのがパターンでした。
が、今回はもう最初から面白い。
予想していたのは、長篠の戦いあたりがスタートで、信幸・信繁兄弟の幼少期から入ると思っていました。が、幼少期はぶっとばして、いつも通りの子役からなんてことはせず、武田家滅亡の直前からのスタートで、堺さんと大泉さんに14~5歳をやらせた。たぶん、正解だと思う。
その堺さんと大泉さん。始まる前は「逆じゃね?」と思ったけど、すごくしっくりくる。そんでなにより、おとーちゃんの草刈正雄。もーぴったりすぎ。(昔のNHKの「真田太平記」で幸村(信繁)役だったらしい。)
お話もすばらしい。わかりやすい。展開早くてだれない。そして大河なのにところどころに笑いを差し込んでくる。いーねー!
そして、過去の大河ドラマでよく不満に思っていたのは、戦闘などがあった時にその地理的な位置関係などの説明が少なく、なんでその結果になったのか、よくわからないことが多かった。
しかし、今回は非常にわかりやすい地図と共に背景を説明してくれるので、理解が早くて話に入りやすい。この地図がいい!(オープニングのタイトルロールで、「シブサワ・コウ」の名前を見たときはビビりました。)
ひとまず二話まで終わった時点では先が楽しみで仕方がないです。
…そして、Twitterの「#真田丸どうでしょう」に爆笑。
…さて、今年の大河ドラマ「真田丸」が面白いです!すごく!
大河ドラマはどうしても、最初のほうは、時代の背景や主人公の特に幼少期のエピソードなどの説明が主になってしまい、最初の二か月ぐらいは我慢してみてると、そのうち面白くなってくる。というのがパターンでした。
が、今回はもう最初から面白い。
予想していたのは、長篠の戦いあたりがスタートで、信幸・信繁兄弟の幼少期から入ると思っていました。が、幼少期はぶっとばして、いつも通りの子役からなんてことはせず、武田家滅亡の直前からのスタートで、堺さんと大泉さんに14~5歳をやらせた。たぶん、正解だと思う。
その堺さんと大泉さん。始まる前は「逆じゃね?」と思ったけど、すごくしっくりくる。そんでなにより、おとーちゃんの草刈正雄。もーぴったりすぎ。(昔のNHKの「真田太平記」で幸村(信繁)役だったらしい。)
お話もすばらしい。わかりやすい。展開早くてだれない。そして大河なのにところどころに笑いを差し込んでくる。いーねー!
そして、過去の大河ドラマでよく不満に思っていたのは、戦闘などがあった時にその地理的な位置関係などの説明が少なく、なんでその結果になったのか、よくわからないことが多かった。
しかし、今回は非常にわかりやすい地図と共に背景を説明してくれるので、理解が早くて話に入りやすい。この地図がいい!(オープニングのタイトルロールで、「シブサワ・コウ」の名前を見たときはビビりました。)
ひとまず二話まで終わった時点では先が楽しみで仕方がないです。
…そして、Twitterの「#真田丸どうでしょう」に爆笑。
2015年11月5日木曜日
2015年10月22日木曜日
SJISのCSVファイルを各カラムの操作と条件による絞り込みを行い、UTF-8のCSVファイルを出力する処理をLINQで。(改)
もともとは「ラムダ式を利用したリファクタリングの例 その2」で扱った後、さらに「SJISのCSVファイルを各カラムの操作と条件による絞り込みを行い、UTF-8のCSVファイルを出力する処理をLINQで。」で修正版を示したネタです。改二ですな。
こんな要求に対する処理を書いていました。
という処理になります。日本語とほぼ一対一にコードが対応してます。ちなみに、.net 2.0相当でコードを書くとこんな感じ。
こんな要求に対する処理を書いていました。
- Shift-JISのCSVファイルを入力し、UTF-8のCSVファイルを出力する。
- 入力したCSVの各カラムは、固定長で前後に空白が入る可能性があり、その空白は除去して出力する。
- 各行の先頭のカラムはIDになっていて、特定のIDのみ出力対象とする。
inFileが入力ファイルのパス、outFileが出力ファイルのパスとして、絞り込みの条件を「先頭カラムが奇数」とすると、以下のコードで拡張メソッドとか作らなくても要求が満たせてしまいますね。
File.WriteAllLines(
outFile,
File.ReadLines(inFile, Encoding.GetEncoding("shift-jis"))
.Select(line => line.Split(','))
.Where(items => int.Parse(items[0]) % 2 != 0)
.Select(items => string.Join(",", items.Select(item => item.Trim()))));
- inFileからShift-JISで各行を読み込み、
- ',' で分割し、
- 先頭カラムが奇数の行について、
- 各カラムの前後の空白を除去した上で再度 ',' で結合し、
- outFileに書き込む。
という処理になります。日本語とほぼ一対一にコードが対応してます。ちなみに、.net 2.0相当でコードを書くとこんな感じ。
var sb = new StringBuilder();
string line;
using (var sr = new StreamReader(inFile, Encoding.GetEncoding("shift-jis")))
using (var sw = new StreamWriter(outFile))
{
while ((line = sr.ReadLine()) != null)
{
var items = line.Split(',');
sb.Length = 0;
if (int.Parse(items[0]) % 2 != 0)
{
foreach (var item in items)
{
sb.Append(item.Trim()).Append(',');
}
sw.WriteLine(sb.ToString(0, sb.Length - 1));
}
}
}
雲泥の差がありますねぇ…。
ラベル:
C#
2015年7月6日月曜日
C#でLEFT OUTER JOIN (左外部結合)
LINQを使って、「LEFT OUTER JOIN」をしたかった。普通のJoinだとINNER JOINなので、少し工夫する必要がありそう。ググってみると、以下のようなコードが一般的なようだ。
ちなみにこれは、MSDNの「方法 : 左外部結合を実行する (C# プログラミング ガイド)」から。
大体どこを見てもこんな感じで、ほとんど左外部結合をしたいときの慣用句(イディオム)みたいなもののよう。とはいえ、このコードを見て「あ、左外部結合させたいんだな」と思える人がどれくらいいるか。要は、コードから意図が解りづらいので、あまり好みじゃないなぁ。と。
もう少し、コードを見て左外部結合であることが解るように、拡張メソッドを作ってみた。こんなの。
Enumerable.Joinメソッドと比べると、最後のパラメータが余計についてます。これはOuterの要素に対して合致するInnerの要素がなかった時の代替要素を指定するもの。Null Objectだと思っておけばよいと思います。
あと、名前は長いのを嫌い、「OuterJoin」としています。タイプパラメータからも、左が外なのは明らかなので、特に問題はないと思っています。
ちなみに、これをライブラリ的に用意するなら、GroupJoinするときにEqautityComparerを指定するパターン、それと、DefaultIfEmptyでTInnerのデフォルト値を自動的に使うパターン、その組み合わせで4つのオーバーロードを、用意しておくのがよいと思います。
さて、テストします。
結果はこう。
…右外部結合?RIGHT OUTER JOINか。僕自身使ったことないですが、必要なら右左を入れ替えてあげればいいはず。上のコードの20行目から28行目を、こんな感じに置き換えてみる。
結果はこう。
うん。いんじゃないかな?
…完全外部結合?…FULL OUTER JOIN…。必要?それ。
使い道が解らなくてモチベーションゼロだけど、要するに左外部結合+右のみに存在するレコードを、編集してUnionすればいいんじゃないかな?多分。
var query = from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj.DefaultIfEmpty()
select new
{
person.FirstName,
PetName = (subpet == null ? String.Empty : subpet.Name)
};
ちなみにこれは、MSDNの「方法 : 左外部結合を実行する (C# プログラミング ガイド)」から。
大体どこを見てもこんな感じで、ほとんど左外部結合をしたいときの慣用句(イディオム)みたいなもののよう。とはいえ、このコードを見て「あ、左外部結合させたいんだな」と思える人がどれくらいいるか。要は、コードから意図が解りづらいので、あまり好みじゃないなぁ。と。
もう少し、コードを見て左外部結合であることが解るように、拡張メソッドを作ってみた。こんなの。
public static class EnumerableEx
{
public static IEnumerable<TResult> OuterJoin<TOuter, TInner, TKey, TResult>
(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector,
TInner innerDefaultValue)
{
return outer
.GroupJoin(
inner,
outerKeySelector,
innerKeySelector,
(o, i) => new { Out = o, Ins = i.DefaultIfEmpty(innerDefaultValue) })
.SelectMany(g => g.Ins, (g, i) => resultSelector(g.Out, i));
}
}
Enumerable.Joinメソッドと比べると、最後のパラメータが余計についてます。これはOuterの要素に対して合致するInnerの要素がなかった時の代替要素を指定するもの。Null Objectだと思っておけばよいと思います。
あと、名前は長いのを嫌い、「OuterJoin」としています。タイプパラメータからも、左が外なのは明らかなので、特に問題はないと思っています。
ちなみに、これをライブラリ的に用意するなら、GroupJoinするときにEqautityComparerを指定するパターン、それと、DefaultIfEmptyでTInnerのデフォルト値を自動的に使うパターン、その組み合わせで4つのオーバーロードを、用意しておくのがよいと思います。
さて、テストします。
static void Main(string[] args)
{
var products = new[]
{
new { ProductId = 1, Name = "えんぴつ" },
new { ProductId = 2, Name = "けしごむ" },
new { ProductId = 3, Name = "コンパス" },
new { ProductId = 4, Name = "クレヨン" },
};
var sales = new[]
{
new { SaleId = 1, ProductId = 1, Buyer = "○○商会", Quantity = 2 },
new { SaleId = 2, ProductId = 1, Buyer = "××文具店", Quantity = 4 },
new { SaleId = 3, ProductId = 2, Buyer = "△屋", Quantity = 3 },
new { SaleId = 4, ProductId = 4, Buyer = "○○商会", Quantity = 1 },
new { SaleId = 5, ProductId = 5, Buyer = "○○商会", Quantity = 1 },
};
var nosaled
= new { SaleId = 0, ProductId = 0, Buyer = "(no sales)", Quantity = 0 };
var salesInfo = products.OuterJoin(
sales,
p => p.ProductId,
s => s.ProductId,
(p, s) => new { p.Name, s.Buyer, s.Quantity },
nosaled);
foreach (var i in salesInfo)
{
Console.WriteLine("{0}, {1}, {2}", i.Name, i.Buyer, i.Quantity);
}
}
結果はこう。
えんぴつ, ○○商会, 2 えんぴつ, ××文具店, 4 けしごむ, △屋, 3 コンパス, (no sales), 0 クレヨン, ○○商会, 1
…右外部結合?RIGHT OUTER JOINか。僕自身使ったことないですが、必要なら右左を入れ替えてあげればいいはず。上のコードの20行目から28行目を、こんな感じに置き換えてみる。
var noproduct = new { ProductId = 0, Name = "(no item)" };
var salesInfo = sales.OuterJoin(
products,
s => s.ProductId,
p => p.ProductId,
(s, p) => new { p.Name, s.Buyer, s.Quantity },
noproduct);
結果はこう。
えんぴつ, ○○商会, 2 えんぴつ, ××文具店, 4 けしごむ, △屋, 3 クレヨン, ○○商会, 1 (no item), ○○商会, 1
うん。いんじゃないかな?
…完全外部結合?…FULL OUTER JOIN…。必要?それ。
使い道が解らなくてモチベーションゼロだけど、要するに左外部結合+右のみに存在するレコードを、編集してUnionすればいいんじゃないかな?多分。
ラベル:
C#
2015年7月3日金曜日
GroupByとToLookup
ここしばらく、C#関連記事ではGroupByを使ったものが続いています。
ところで、.net Frameworkには、GroupByと非常によく似た「ToLookup」というEnumerable拡張メソッドがあります。大体名前のイメージで、GroupByは遅延実行で、ToLookupは即時実行だと思い、基本的に使い分けていました。
もう少し調べてみると、ToLookupはその名の通りルックアップテーブルを作るメソッドで、戻されるLookupクラスは、キーからのルックアップを機能として有している。と。
ところがふと、過去にGroupByを使っていて、ToLookupを使ったほうがよいケースがあったりするんじゃないかと不安になってきまして。たとえば何も考えずにGroupByを使っていた箇所で、ToLookupを使ったほうが実はよかった。とかいうケースがあったらいやだなぁ。と。
なので、とりあえず処理時間を計ってみました。使ったのはこんなコード。
先日の『ToDictionaryで重複のない辞書を作る』と同様に、コレクションからキー重複を排除した辞書を作る処理にGroupByを使ってみて、単純にGroupBy→ToLookupに置き換えたときにどれくらい処理速度の差があるか?ほんの少しGroupByが早いんじゃないかな?と予想。
結果は、
GroupBy … 6155msec。
ToLookup … 6081msec。
となり、予想に反してほんの誤差レベルとはいえGroupByのほうが遅い結果に。なんでだろう?と思ってソースコードを調べてみた。
GroupByは大体こんな感じ。
それに対して、ToLookupはこんな感じ。
あー。これだとほぼ即時実行か遅延実行かの違いしかないですねぇ。これならToLookupが若干速いのも納得できる。
というか、そうするとGroupByの存在意義が解らなくなったので、ちょっと調べてみたら、Stackoverflowに「Why are ToLookup and GroupBy different?」こんな質問があって、その回答が以下。
気にしなければならない速度差では全くないですしね。
ところで、.net Frameworkには、GroupByと非常によく似た「ToLookup」というEnumerable拡張メソッドがあります。大体名前のイメージで、GroupByは遅延実行で、ToLookupは即時実行だと思い、基本的に使い分けていました。
もう少し調べてみると、ToLookupはその名の通りルックアップテーブルを作るメソッドで、戻されるLookupクラスは、キーからのルックアップを機能として有している。と。
ところがふと、過去にGroupByを使っていて、ToLookupを使ったほうがよいケースがあったりするんじゃないかと不安になってきまして。たとえば何も考えずにGroupByを使っていた箇所で、ToLookupを使ったほうが実はよかった。とかいうケースがあったらいやだなぁ。と。
なので、とりあえず処理時間を計ってみました。使ったのはこんなコード。
static void Main(string[] args)
{
var rnd = new Random(DateTime.Now.Millisecond);
var items = Enumerable.Range(0, 10000000).Select(_ => new
{
Key1 = rnd.Next(10),
Key2 = rnd.Next(100),
Value = rnd.Next(10000)
});
var sw = new Stopwatch();
sw.Start();
var dic = items.GroupBy(i => new { i.Key1, i.Key2 })
.ToDictionary(g => g.Key, g => g.First().Value);
sw.Stop();
Console.WriteLine("Elapsed:{0}msec", sw.ElapsedMilliseconds);
}
先日の『ToDictionaryで重複のない辞書を作る』と同様に、コレクションからキー重複を排除した辞書を作る処理にGroupByを使ってみて、単純にGroupBy→ToLookupに置き換えたときにどれくらい処理速度の差があるか?ほんの少しGroupByが早いんじゃないかな?と予想。
結果は、
GroupBy … 6155msec。
ToLookup … 6081msec。
となり、予想に反してほんの誤差レベルとはいえGroupByのほうが遅い結果に。なんでだろう?と思ってソースコードを調べてみた。
GroupByは大体こんな感じ。
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return new GroupedEnumerable<TSource, TKey, TSource>(
source, keySelector, IdentityFunction<TSource>.Instance, null);
}
internal class GroupedEnumerable<TSource, TKey, TElement>
: IEnumerable<IGrouping<TKey, TElement>>
{
public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
{
return Lookup<TKey, TElement>.Create<TSource>(
source, keySelector, elementSelector, comparer).GetEnumerator();
}
}
それに対して、ToLookupはこんな感じ。
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return Lookup<TKey, TSource>.Create(
source, keySelector, IdentityFunction<TSource>.Instance, null);
}
あー。これだとほぼ即時実行か遅延実行かの違いしかないですねぇ。これならToLookupが若干速いのも納得できる。
というか、そうするとGroupByの存在意義が解らなくなったので、ちょっと調べてみたら、Stackoverflowに「Why are ToLookup and GroupBy different?」こんな質問があって、その回答が以下。
What happens when you call ToLookup on an object representing a remote database table with a billion rows in it?なるほど。例えばデータソースがObjectではなくDatabaseだったりしたときに、即時実行しないで済むならそうしたい。LINQのメソッドはデータソースを問わないわけだから、基本的にはGroupByを使い、明示的に即時実行にしたい場合や、実行後のルックアップが必要なら、ToLookupを使うべし。と、解釈して納得できた。
気にしなければならない速度差では全くないですしね。
ラベル:
C#
2015年6月30日火曜日
『月光~the lunatic~』
イブニングで5週掲載された、ウチヤマユージさんの『月光~the lunatic~』の単行本が発売されたようなので、おススメを。

表題作と他一遍の中編集。イブニング掲載時に読みましたが、すごく良かった。絵も話もとても好み。
静かに始まる第一話。一見他愛ない日常に見えて、ちらほらと異常がちりばめられる。
話が進むと時間軸を行ったり来たりしながら展開していき、少しずつ全容が見えてくる。
すべてが明らかになった後、結末は「んなあほな」と思いつつ、なんだか妙に晴れやかな気分。
この作者さんは知りませんでしたが、今後に期待大です。
表題作と他一遍の中編集。イブニング掲載時に読みましたが、すごく良かった。絵も話もとても好み。
静かに始まる第一話。一見他愛ない日常に見えて、ちらほらと異常がちりばめられる。
話が進むと時間軸を行ったり来たりしながら展開していき、少しずつ全容が見えてくる。
すべてが明らかになった後、結末は「んなあほな」と思いつつ、なんだか妙に晴れやかな気分。
この作者さんは知りませんでしたが、今後に期待大です。
ラベル:
漫画
登録:
投稿 (Atom)