2100年1月1日金曜日
2017年2月12日日曜日
バインディング
ViewのデータをPostする際に、Nameの名前が所定のルールに従っていれば自動的に
バインドしてくれるので、Controllerの引数から受け取ることができます。
基本は、InputタグのNameに クラス名.プロパティとかけばバインドしてくれます。
あとは、プロパティがリストだという場合は、 クラス名.プロパティ[インデックス]
クラス自体がリストで受け取るのであれば クラス名[インデックス].プロパティ
といった感じでかけば受け取ることができます。
わかりやすくするため、ViewでHTMLをハードコードします。
Models/Sample.cs
IDとNameを持つだけのクラスです。
適当にHomeという名前のControllerを作成して以下のように書きました
Controllers/HomeController.cs
Views/Home/Create.cshtml

@modelにクラスが設定されていれば、Nameのところでクラス名を省略できます。
Views/Home/Create.cshtml
今度は、クラス内にListがある時
Models/Sample.cs
Views/Home/Create.cshtml
リストはプロパティ名に[インデックス]番号つければバインドできます

今度は、Dictionaryをモデルに持っている時です
Models/Sample.cs
Controllers/HomeController.cs
Views/Home/Create.cshtml
KeyValueのうち、Keyは inputのhiddenに、Valueは取得したいinput要素のNameに指定します。
KeyとValueをペアリングするために Nameにプロパティ名[文字列] が一致する者同士を KeyValueのペアとみなします。
<input type = "hidden" name="プロパティ名[文字列].key" value="キー名" />
<input type = "text" name="プロパティ名[文字列].value" value="値" />
[文字列]はループ処理とかを考えると数字が来やすいけども
keyとvalueをペアリングするための識別子なので、任意の文字を指定できます
今度は、Controllerで受け取る引数をリスト(List)にしてみます。
Models/Sample.cs
Controllers/HomeController.cs
Viewes/Home/Create.cshtml
クラス内でListを使い、そのクラスをリストで受けるとなると、今までの方法を組み合わせるだけです
Models/Sample.cs
Controllers/HomeController.cs
Views/Home/Create.cshtml
何が複数なのかを考えればクラスに[数字]をつけるかプロパティに[数字]をつけるか明確ですね
ちなみに、クラスのインスタンスに、一加工してから格納したいので
ひとまずリストで受け取りたいなんて場合、いちいちクラスを作らなくてもバインドしてくれます
Models/Sample.cs
Controllers/HomeController.cs
を用意。
名前をhogeにしたので、Viewにもhogeの名前でnameにつけます。
Views/Home/Create.cshtml
これで、 List list にも List hogeにもバインドされます。
バインドしてくれるので、Controllerの引数から受け取ることができます。
基本は、InputタグのNameに クラス名.プロパティとかけばバインドしてくれます。
あとは、プロパティがリストだという場合は、 クラス名.プロパティ[インデックス]
クラス自体がリストで受け取るのであれば クラス名[インデックス].プロパティ
といった感じでかけば受け取ることができます。
わかりやすくするため、ViewでHTMLをハードコードします。
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
}
}
IDとNameを持つだけのクラスです。
適当にHomeという名前のControllerを作成して以下のように書きました
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SampleCode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Models.Sample sample)
{
return View();
}
}
}
ブレイクポイントを設定して確認します。Views/Home/Create.cshtml
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}

@modelにクラスが設定されていれば、Nameのところでクラス名を省略できます。
Views/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
今度は、クラス内にListがある時
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
public List Memo { get; set; }
}
}
Views/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
リストはプロパティ名に[インデックス]番号つければバインドできます

今度は、Dictionaryをモデルに持っている時です
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
public Dictionary Hash { get; set; }
}
}
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SampleCode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Models.Sample sample)
{
return View();
}
}
}
Views/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
KeyValueのうち、Keyは inputのhiddenに、Valueは取得したいinput要素のNameに指定します。
KeyとValueをペアリングするために Nameにプロパティ名[文字列] が一致する者同士を KeyValueのペアとみなします。
<input type = "hidden" name="プロパティ名[文字列].key" value="キー名" />
<input type = "text" name="プロパティ名[文字列].value" value="値" />
[文字列]はループ処理とかを考えると数字が来やすいけども
keyとvalueをペアリングするための識別子なので、任意の文字を指定できます
今度は、Controllerで受け取る引数をリスト(List
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
}
}
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SampleCode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(List list)
{
return View();
}
}
}
Viewes/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
基本は、クラス名[数字].プロパティ ですが、modelで明示してあるので省略してあるだけです。クラス内でListを使い、そのクラスをリストで受けるとなると、今までの方法を組み合わせるだけです
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
public List Memo { get; set; }
}
}
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SampleCode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(List list)
{
return View();
}
}
}
Views/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
何が複数なのかを考えればクラスに[数字]をつけるかプロパティに[数字]をつけるか明確ですね
ちなみに、クラスのインスタンスに、一加工してから格納したいので
ひとまずリストで受け取りたいなんて場合、いちいちクラスを作らなくてもバインドしてくれます
Models/Sample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace SampleCode.Models
{
public class Sample
{
public int ID { get; set; }
public string Name { get; set; }
}
}
Controllers/HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SampleCode.Controllers
{
public class HomeController : Controller
{
// GET: Home
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(List list, List hoge)
{
return View();
}
}
}
Modelに定義せずに List名前をhogeにしたので、Viewにもhogeの名前でnameにつけます。
Views/Home/Create.cshtml
@model SampleCode.Models.Sample
@{
ViewBag.Title = "Create";
}
Create
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
これで、 List
2015年11月30日月曜日
正規表現によるSplit
数字部分でSplit
正規表現の部分も取得したければ、グループ化すれば
取得してくれる。
正規表現にマッチすると、分割し、捨てられる。
ただし、かっこでくくっておくと、それは取ってくれる。
極端なことを言えば、数字で分割するけど、分割後偶数はとっておこう。
なんて思うと
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Regex splitReg = new Regex(@"[0-9]+");
string[] a = splitReg.Split("AB12CD34EF");
foreach (string data in a)
{
Console.WriteLine(data);
}
}
}
}
AB CD EF正規表現の部分が区切りとみなされ分割される。
正規表現の部分も取得したければ、グループ化すれば
取得してくれる。
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Regex splitReg = new Regex(@"([0-9]+)");
string[] a = splitReg.Split("AB12CD34EF");
foreach (string data in a)
{
Console.WriteLine(data);
}
}
}
}
AB 12 CD 34 EF
正規表現にマッチすると、分割し、捨てられる。
ただし、かっこでくくっておくと、それは取ってくれる。
極端なことを言えば、数字で分割するけど、分割後偶数はとっておこう。
なんて思うと
using System;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Regex splitReg = new Regex(@"(?:([02468])|[13579])+");
string[] a = splitReg.Split("A1B2C3D45E67F8G9H");
foreach (string data in a)
{
Console.WriteLine(data);
}
}
}
}
A B 2 C D 4 E 6 F 8 G H
2015年8月30日日曜日
2015年1月4日日曜日
LINQメモ
・LINQ SampleCode
ど忘れした時のための参考サンプルコード
・メソッド一覧
Aggregate
All
Any
Count
DefaultIfEmpty
・いろいろ
大文字、小文字を無視してDistinct
ど忘れした時のための参考サンプルコード
・メソッド一覧
Aggregate
All
Any
Count
DefaultIfEmpty
・いろいろ
大文字、小文字を無視してDistinct
Distinct
■public static IEnumerable Distinct
(this IEnumerable source);
// 概要:
// 既定の等値比較子を使用して値を比較することにより、シーケンスから一意の要素を返します。
//
// パラメーター:
// source:
// 重複する要素を削除する対象となるシーケンス。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ソース シーケンスの一意の要素を格納する System.Collections.Generic.IEnumerable。
//
// 例外:
// System.ArgumentNullException:
// source が null です。
0 1 2 3 4 5 4 3 2 1 0 の重複を取り除く
実行結果
(this IEnumerable
// 概要:
// 既定の等値比較子を使用して値を比較することにより、シーケンスから一意の要素を返します。
//
// パラメーター:
// source:
// 重複する要素を削除する対象となるシーケンス。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ソース シーケンスの一意の要素を格納する System.Collections.Generic.IEnumerable
//
// 例外:
// System.ArgumentNullException:
// source が null です。
0 1 2 3 4 5 4 3 2 1 0 の重複を取り除く
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
int[] num = { 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0 };
foreach (var n in num.Distinct()) {
Console.WriteLine(n);
}
}
}
}
実行結果
0 1 2 3 4 5
2015年1月3日土曜日
DefaultIfEmpty
■public static IEnumerable DefaultIfEmpty(this IEnumerable source);
// 概要:
// 指定したシーケンスの要素を返します。シーケンスが空の場合はシングルトン コレクションにある型パラメーターの既定値を返します。
//
// パラメーター:
// source:
// シーケンスが空の場合に、既定値を返すシーケンス。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// source が空の場合、TSource 型の既定値を格納する System.Collections.Generic.IEnumerable
// オブジェクト。それ以外の場合は source。
//
// 例外:
// System.ArgumentNullException:
// source が null です。
最初に配列の要素数を用意し、あるルールに従ってその数字の要素数に値を格納する時
残った部分が未定義になってしまうのでDefault値を設定してしまおうという場合
ちなみに、Listに使うとnullが代入されます
// 概要:
// 指定したシーケンスの要素を返します。シーケンスが空の場合はシングルトン コレクションにある型パラメーターの既定値を返します。
//
// パラメーター:
// source:
// シーケンスが空の場合に、既定値を返すシーケンス。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// source が空の場合、TSource 型の既定値を格納する System.Collections.Generic.IEnumerable
// オブジェクト。それ以外の場合は source。
//
// 例外:
// System.ArgumentNullException:
// source が null です。
最初に配列の要素数を用意し、あるルールに従ってその数字の要素数に値を格納する時
残った部分が未定義になってしまうのでDefault値を設定してしまおうという場合
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
int[] numList = new int[10];
numList[3] = 3;
numList[5] = 5;
var numDefault = numList.DefaultIfEmpty();
foreach (var num in numDefault) {
Console.WriteLine(num);
}
}
}
}
要素番号3,5以外は0になります。ちなみに、List
using System;
using System.Collections.Generic;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
List strList = new List();
Console.WriteLine(strList.Count()); //0
var strDefault = strList.DefaultIfEmpty();
Console.WriteLine(strDefault.Count()); //0
foreach (var str in strDefault) {
Console.WriteLine(str == null); //True
}
}
}
}
Count
■public static int Count
(this IEnumerable source, Func predicate);
// 概要:
// 条件を満たす、指定されたシーケンス内の要素の数を表す数値を返します。
//
// パラメーター:
// source:
// テストおよびカウントする要素が格納されているシーケンス。
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 述語関数の条件を満たす、シーケンス内の要素数を表す数値。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
//
// System.OverflowException:
// source 内の要素数が System.Int32.MaxValue を超えています。
(this IEnumerable
// 概要:
// 条件を満たす、指定されたシーケンス内の要素の数を表す数値を返します。
//
// パラメーター:
// source:
// テストおよびカウントする要素が格納されているシーケンス。
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 述語関数の条件を満たす、シーケンス内の要素数を表す数値。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
//
// System.OverflowException:
// source 内の要素数が System.Int32.MaxValue を超えています。
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
string test = "gooooooooooooooooooooooooooogle";
//LINQで oの個数を調べる
int count = test.Count(c => c == 'o'); //ラムダ式を渡す
Console.WriteLine("oの数は{0}個です", count); //oの数は27個です
}
}
}
2015年1月2日金曜日
AsParallel
■public static ParallelQuery AsParallel
(this IEnumerable source);
// 概要:
// クエリの並列化を有効にします。
//
// パラメーター:
// source:
// System.Linq.ParallelQuery に変換する System.Collections.Generic.IEnumerable。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ParallelEnumerable 拡張メソッドにバインドされる System.Linq.ParallelQuery としての
// source。
//
// 例外:
// System.ArgumentNullException:
// source が null 参照 (Visual Basic の場合は Nothing) です。
2コアのPCで実行したとき下記のような差がでました。
Serial :00:00:01.0920000
Parallel:00:00:00.7488000
並列化された場合どの順に処理が完了するか不明なため
順番が保障されなくなる点など気をつける必要が出てきますね。
(this IEnumerable
// 概要:
// クエリの並列化を有効にします。
//
// パラメーター:
// source:
// System.Linq.ParallelQuery
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ParallelEnumerable 拡張メソッドにバインドされる System.Linq.ParallelQuery
// source。
//
// 例外:
// System.ArgumentNullException:
// source が null 参照 (Visual Basic の場合は Nothing) です。
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] a = new int[100000000];
a[a.Length - 1] = 1;
var start1 = DateTime.Now;
var bySerial = a.Count(c => c == 1);
Console.WriteLine("Serial :{0}", DateTime.Now - start1);
var start2 = DateTime.Now;
var byParallel = a.AsParallel().Count(c => c == 1);
Console.WriteLine("Parallel:{0}", DateTime.Now - start2);
}
}
}
2コアのPCで実行したとき下記のような差がでました。
Serial :00:00:01.0920000
Parallel:00:00:00.7488000
並列化された場合どの順に処理が完了するか不明なため
順番が保障されなくなる点など気をつける必要が出てきますね。
Any
■public static bool Any
(this IEnumerable source);
// 概要:
// シーケンスに要素が含まれているかどうかを判断します。
//
// パラメーター:
// source:
// 空かどうかを確認する System.Collections.Generic.IEnumerable。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ソース シーケンスに要素が含まれている場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source が null です。
引数がないと単純に要素を持っているかどうかを判定するだけのようですね。
■public static bool Any(this IEnumerable source, Func predicate);
// 概要:
// シーケンスの任意の要素が条件を満たしているかどうかを判断します。
//
// パラメーター:
// source:
// 述語を適用する要素を含む System.Collections.Generic.IEnumerable。
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 指定された述語でソース シーケンスの要素がテストに合格する場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
要素中に少なくとも一つ、引数に渡した関数がtrueであればtrueを返す
(this IEnumerable
// 概要:
// シーケンスに要素が含まれているかどうかを判断します。
//
// パラメーター:
// source:
// 空かどうかを確認する System.Collections.Generic.IEnumerable
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// ソース シーケンスに要素が含まれている場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source が null です。
引数がないと単純に要素を持っているかどうかを判定するだけのようですね。
■public static bool Any
// 概要:
// シーケンスの任意の要素が条件を満たしているかどうかを判断します。
//
// パラメーター:
// source:
// 述語を適用する要素を含む System.Collections.Generic.IEnumerable
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 指定された述語でソース シーケンスの要素がテストに合格する場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
要素中に少なくとも一つ、引数に渡した関数がtrueであればtrueを返す
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
int[] emptyList = { };
//要素はありますか?
Console.WriteLine(emptyList.Any()); //False
int[] numberList = { 1, 3, 5, 7 };
//要素はありますか?
Console.WriteLine(numberList.Any()); //True
//2の倍数はありますか?
Console.WriteLine(numberList.Any(num => num % 2 == 0)); //False
//3の倍数はありますか?
Console.WriteLine(numberList.Any(num => num % 3 == 0)); //True
}
}
}
All
■public static bool All
(this IEnumerable source, Func predicate);
// 概要:
// シーケンスのすべての要素が条件を満たしているかどうかを判断します。
//
// パラメーター:
// source:
// 述語を適用する要素を格納している System.Collections.Generic.IEnumerable。
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 指定された述語でソース シーケンスのすべての要素がテストに合格する場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
例えば、商品のリストがあるとして負の値があればエラーとしたい時
(this IEnumerable
// 概要:
// シーケンスのすべての要素が条件を満たしているかどうかを判断します。
//
// パラメーター:
// source:
// 述語を適用する要素を格納している System.Collections.Generic.IEnumerable
//
// predicate:
// 各要素が条件を満たしているかどうかをテストする関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 指定された述語でソース シーケンスのすべての要素がテストに合格する場合は true。それ以外の場合は false。
//
// 例外:
// System.ArgumentNullException:
// source または predicate が null です。
例えば、商品のリストがあるとして負の値があればエラーとしたい時
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
int[] itemList = new int[] { 110, 210, 310, -100 };
if (itemList.All(num => num < 0)) {
Console.WriteLine("引数に問題ありません");
}else{
Console.WriteLine("引数に問題あります");
}
}
}
}
こんな風にかけると。
Aggregate
各要素に対しアキュームレートするメソッドです。
アキュムレーターとは、演算結果を累積する処理のことを指すようです。
■public static TSource Aggregate
(this IEnumerable source, Func func);
// 概要:
// シーケンスにアキュムレータ関数を適用します。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source または func が null です。
//
// System.InvalidOperationException:
// source に要素が含まれていません。
■public static TAccumulate Aggregate
(this IEnumerable source, TAccumulate seed, Func func);
//
// 概要:
// シーケンスにアキュムレータ関数を適用します。指定されたシード値が最初のアキュムレータ値として使用されます。
//
// パラメーター:
// source:
// 集計対象の System.Collections.Generic.IEnumerable。
//
// seed:
// 最初のアキュムレータ値。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// TAccumulate:
// アキュムレータ値の型。
//
// 戻り値:
// 最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source または func が null です。
■public static TResult Aggregate
(this IEnumerable source, TAccumulate seed, Func func, Func resultSelector);
// 概要:
// シーケンスにアキュムレータ関数を適用します。
// 指定したシード値は最初のアキュムレータ値として使用され、
// 指定した関数は結果値の選択に使用されます。
//
// パラメーター:
// source:
// 集計対象の System.Collections.Generic.IEnumerable。
//
// seed:
// 最初のアキュムレータ値。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// resultSelector:
// 最終的なアキュムレータ値を結果値に変換する関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// TAccumulate:
// アキュムレータ値の型。
//
// TResult:
// 結果の値の型。
//
// 戻り値:
// 変換された最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source、func、または resultSelector が null です。
aggregateメソッドでは名前の通り何かを行って集計するメソッドのようです。
こんなシチュエーションを考えてみました。
レジをイメージして商品のリスト(外税)に対し、お金を渡し消費税を掛けた金額を
差し引いていき、その結果いくら残ったか知りたいというような状況
商品のリストに3つ格納されているので3回繰り返し処理を行います。
この時ラムダ式内の各変数は以下のようになります。
1回目
money:1000 //initMoneyの値を受け取る
num : 110 //itemListの最初の値を受け取る
↓
money :885 //1個目の値が差し引かれる
2回目
money:885 //1ループ目の結果を受け取る
num : 210 //itemListの2つ目の値を受け取る
↓
money :665 //2個目の値が差し引かれる
3回目
money:665 //2ループ目の結果を受け取る
num : 310 //itemListの3つ目の値を受け取る
↓
money :340 //3個目の値が差し引かれる
340が戻り値となる
これが2引数の場合ですね。
TAccumulate seed
Func func
せっかくなので3引数の場合も試してみます。
上の例では消費税をかけたものを切り捨てして引き算しています。
消費税をかけたのち、切り捨てせずに引き算して一番最後に切り捨てしてみましょう。
確認。
消費税をかけて切り捨てをした結果を引き算すると
340になります。
まずは、切り捨てを辞めて小数で結果を返してみますか。
338.5に対し切り捨てを行ってみます。
第3引数で切り捨ての処理をしてみます。
(money, num) => (money - num * tax)で集約処理をした結果を
money2 => Math.Floor(money2) の式に渡しその結果を出力しています。
その結果338がかえってきます。
これが3引数の場合ですね。
TAccumulate seed
Func func
Func resultSelector
では、1引数の時はというと最初の要素がmoneyに渡され、第二要素以降がnumに渡されます。
(money, num) => (money - num * tax)
つまり、最初の例は
もっと他の最適な例があるのかもしれないのでそういう時に使うとします。
念のためラムダ式内の各変数は以下のようになります。
1回目
money:1000 //itemListの最初の値を受け取る
num : 110 //itemListの2番目の値を受け取る
↓
money :885 //1個目の値が差し引かれる
2回目
money:885 //1ループ目の結果を受け取る
num : 210 //itemListの3番目の値を受け取る
↓
money :665 //2個目の値が差し引かれる
3回目
money:665 //2ループ目の結果を受け取る
num : 310 //itemListの4番目の値を受け取る
↓
money :340 //3個目の値が差し引かれる
340が戻り値となる
アキュムレーターとは、演算結果を累積する処理のことを指すようです。
■public static TSource Aggregate
(this IEnumerable
// 概要:
// シーケンスにアキュムレータ関数を適用します。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// 戻り値:
// 最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source または func が null です。
//
// System.InvalidOperationException:
// source に要素が含まれていません。
■public static TAccumulate Aggregate
(this IEnumerable
//
// 概要:
// シーケンスにアキュムレータ関数を適用します。指定されたシード値が最初のアキュムレータ値として使用されます。
//
// パラメーター:
// source:
// 集計対象の System.Collections.Generic.IEnumerable
//
// seed:
// 最初のアキュムレータ値。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// TAccumulate:
// アキュムレータ値の型。
//
// 戻り値:
// 最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source または func が null です。
■public static TResult Aggregate
(this IEnumerable
// 概要:
// シーケンスにアキュムレータ関数を適用します。
// 指定したシード値は最初のアキュムレータ値として使用され、
// 指定した関数は結果値の選択に使用されます。
//
// パラメーター:
// source:
// 集計対象の System.Collections.Generic.IEnumerable
//
// seed:
// 最初のアキュムレータ値。
//
// func:
// 各要素に対して呼び出すアキュムレータ関数。
//
// resultSelector:
// 最終的なアキュムレータ値を結果値に変換する関数。
//
// 型パラメーター:
// TSource:
// source の要素の型。
//
// TAccumulate:
// アキュムレータ値の型。
//
// TResult:
// 結果の値の型。
//
// 戻り値:
// 変換された最終的なアキュムレータ値。
//
// 例外:
// System.ArgumentNullException:
// source、func、または resultSelector が null です。
aggregateメソッドでは名前の通り何かを行って集計するメソッドのようです。
こんなシチュエーションを考えてみました。
レジをイメージして商品のリスト(外税)に対し、お金を渡し消費税を掛けた金額を
差し引いていき、その結果いくら残ったか知りたいというような状況
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
double tax = 1.05;
int initMoney = 1000;
int[] itemList = new int[] { 110, 210, 310 };
var resutMoney = itemList.Aggregate(initMoney, (money, num) => (money - (int)(num * tax)));
Console.WriteLine(resutMoney);
}
}
}
商品のリストに3つ格納されているので3回繰り返し処理を行います。
この時ラムダ式内の各変数は以下のようになります。
1回目
money:1000 //initMoneyの値を受け取る
num : 110 //itemListの最初の値を受け取る
↓
money :885 //1個目の値が差し引かれる
2回目
money:885 //1ループ目の結果を受け取る
num : 210 //itemListの2つ目の値を受け取る
↓
money :665 //2個目の値が差し引かれる
3回目
money:665 //2ループ目の結果を受け取る
num : 310 //itemListの3つ目の値を受け取る
↓
money :340 //3個目の値が差し引かれる
340が戻り値となる
これが2引数の場合ですね。
TAccumulate seed
Func
せっかくなので3引数の場合も試してみます。
上の例では消費税をかけたものを切り捨てして引き算しています。
消費税をかけたのち、切り捨てせずに引き算して一番最後に切り捨てしてみましょう。
確認。
消費税をかけて切り捨てをした結果を引き算すると
340になります。
まずは、切り捨てを辞めて小数で結果を返してみますか。
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
double tax = 1.05;
int initMoney = 1000;
int[] itemList = new int[] { 110, 210, 310 };
var resutMoney = itemList.Aggregate((double)initMoney,
(money, num) => (money - num * tax)
);
Console.WriteLine(resutMoney);
}
}
}
これなら、結果は338.5になります。338.5に対し切り捨てを行ってみます。
第3引数で切り捨ての処理をしてみます。
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
double tax = 1.05;
int initMoney = 1000;
int[] itemList = new int[] { 110, 210, 310 };
var resutMoney = itemList.Aggregate((double)initMoney,
(money, num) => (money - num * tax),
money2 => Math.Floor(money2)
);
Console.WriteLine(resutMoney);
}
}
}
(money, num) => (money - num * tax)で集約処理をした結果を
money2 => Math.Floor(money2) の式に渡しその結果を出力しています。
その結果338がかえってきます。
これが3引数の場合ですね。
TAccumulate seed
Func
Func
では、1引数の時はというと最初の要素がmoneyに渡され、第二要素以降がnumに渡されます。
(money, num) => (money - num * tax)
つまり、最初の例は
using System;
using System.Linq;
namespace SampleCode {
class Program {
static void Main(string[] args) {
double tax = 1.05;
int[] itemList = new int[] { 1000, 110, 210, 310 }; //所持金を第一要素に格納した
var resutMoney = itemList.Aggregate((money, num) => (money - (int)(num * tax)));
Console.WriteLine(resutMoney);
}
}
}
結果は一緒ですが、商品のリストに所持金をいれるのは解釈的に気持ち悪いですね。もっと他の最適な例があるのかもしれないのでそういう時に使うとします。
念のためラムダ式内の各変数は以下のようになります。
1回目
money:1000 //itemListの最初の値を受け取る
num : 110 //itemListの2番目の値を受け取る
↓
money :885 //1個目の値が差し引かれる
2回目
money:885 //1ループ目の結果を受け取る
num : 210 //itemListの3番目の値を受け取る
↓
money :665 //2個目の値が差し引かれる
3回目
money:665 //2ループ目の結果を受け取る
num : 310 //itemListの4番目の値を受け取る
↓
money :340 //3個目の値が差し引かれる
340が戻り値となる
LINQ SampleCode
あの書き方どうだったっけというときに参照するようにいろいろコードを書いておく
ってときに見る用にいろんなサンプルコードを置いておく
・特定の文字をカウントする
・数字を倍にして配列で受け取る
・最初に現れる偶数は何番目か?
Select内では、
numをキーにnumListから受け取る数字を値に指定
indexNoをキーに要素数を指定
Firstで2で割った時に0になる物が現れた時終了し
そのオブジェクトのindexNo(要素番号)を返す処理
・動的なAND条件
手っ取り早く、ある文字列の配列に対し、特定の文字全てを含んでいるかチェック
ってときに見る用にいろんなサンプルコードを置いておく
・特定の文字をカウントする
string test = "gooooooooooooooooooooooooooogle";
//LINQで oの個数を調べる
int count = test.Count(c => c == 'o');
Console.WriteLine("oの数は{0}個です", count.ToString());
・数字を倍にして配列で受け取る
int[] num = { 1, 2, 3, 4, 5 };
num = num.Select(n => n * 2).ToArray();
・最初に現れる偶数は何番目か?
int[] numList = { 3, 8, 15, 18 };
Console.WriteLine(numList.Select((num, indexNo) => new { num ,indexNo})
.First(n => n.num % 2 == 0).indexNo);
Selectの第二引数を指定することで要素番号を取得するSelect内では、
numをキーにnumListから受け取る数字を値に指定
indexNoをキーに要素数を指定
Firstで2で割った時に0になる物が現れた時終了し
そのオブジェクトのindexNo(要素番号)を返す処理
・動的なAND条件
手っ取り早く、ある文字列の配列に対し、特定の文字全てを含んでいるかチェック
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] str = { "睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"};
string[] check = { "月", "無" };
var result = str.Where(s => check.All(c => -1 < s.IndexOf(c)));
Console.WriteLine(string.Join(", ", result)); //水無月, 神無月
}
}
}
・動的なOR条件
手っ取り早く、ある文字列の配列に対し、特定の文字がどれか含んでいるかチェック
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] str = { "睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"};
string[] check = { "弥", "無" };
var result = str.Where(s => check.Any(c => -1 < s.IndexOf(c)));
Console.WriteLine(string.Join(", ", result)); //弥生, 水無月, 神無月
}
}
}
2015年1月1日木曜日
LINQを学習してみる
LINQ to Objectsとは
IEnumerableを継承していれば使えるということで
例えばstring型なんかも継承しているので使うことができます。
たとえば、下記文字列にoが何個含まれているか調べるとすると
gooooooooooooooooooooooooooogle
とても便利ですね。
string型の場合一文字ずつ渡されるのでそれをcという変数で受け取り
カウントするさいの条件式を渡してあげているわけですね。
ラムダ式になじみがないとみづらいかもしれませんが
c => c == 'o' は、javascriptで言えばこれと一緒ですね
function(c){ return c == "o" }
LINQを使わないのであれば下記のようになりそうですね。
LINQなら、明示的に1文字ずつ取り出す処理を書かなくてもやってくれるあたりがらくちんなんでしょうね。
と、いうことで使い方がすぐになれないLINQなので少しずつ勉強して使い方を覚えていく予定。
"LINQ to Objects" という用語は、LINQ to SQL [LINQ to SQL] や LINQ to XML などの中間 LINQ プロバイダーまたは API を使用せずに、LINQ クエリを任意の IEnumerable コレクションまたは IEnumerablehttp://msdn.microsoft.com/ja-jp/library/bb397919.aspxコレクションと直接組み合わせて使用することを意味します。
IEnumerableを継承していれば使えるということで
例えばstring型なんかも継承しているので使うことができます。
たとえば、下記文字列にoが何個含まれているか調べるとすると
gooooooooooooooooooooooooooogle
using System;
using System.Linq;
using System.Collections;
namespace SampleCode {
class Program {
static void Main(string[] args) {
string test = "gooooooooooooooooooooooooooogle";
//Inumerableが継承されているか確認する
Console.WriteLine("Inumerable実装されて{0}", (test is IEnumerable) ? "いる" : "いない");
//LINQで oの個数を調べる
int count = test.Count(c => c == 'o'); //ラムダ式を渡す
Console.WriteLine("oの数は{0}個です", count.ToString());
}
}
}
とても便利ですね。
string型の場合一文字ずつ渡されるのでそれをcという変数で受け取り
カウントするさいの条件式を渡してあげているわけですね。
ラムダ式になじみがないとみづらいかもしれませんが
c => c == 'o' は、javascriptで言えばこれと一緒ですね
function(c){ return c == "o" }
LINQを使わないのであれば下記のようになりそうですね。
//LINQで oの個数を調べる
int count = test.Count(c => c == 'o'); //ラムダ式を渡す
Console.WriteLine("oの数は{0}個です", count.ToString());
↓
//LINQで oの個数を調べる
int count = 0;
for (int i = 0; i < test.Length; i++) {
count += (test.Substring(i, 1) == "o") ? 1 : 0;
}
Console.WriteLine("oの数は{0}個です", count.ToString());
LINQなら、明示的に1文字ずつ取り出す処理を書かなくてもやってくれるあたりがらくちんなんでしょうね。
と、いうことで使い方がすぐになれないLINQなので少しずつ勉強して使い方を覚えていく予定。
登録:
投稿 (Atom)