LINQ

where句

using System.Linq;

int[] array = { 3, -5, -1, 0, 2 };

foreach (int elm in array) Console.WriteLine(elm);
→3, -5, -1, 0, 2

クエリ変数 = クエリ式
var pos =
 from n in array
 where n > 0
 select n;

foreach (int elm in pos) Console.WriteLine(elm);
→3, 2

using System.Linq;

int[] array = { 3, -5, -1, 0, 2 };

var pos = array.Where(n => n > 0).Select(n => n);

foreach (int elm in pos) Console.WriteLine(elm);
→3, 2

orderby句

int[] array = { 3, -5, -1, 0, 2 };

var pos =
 from n in array
 where n > 0
 orderby n

foreach (int elm in pos) Console.WriteLine(elm);
→2, 3

orderby n ascending ※デフォルト
orderby n descending

int[] array = { 3, -5, -1, 0, 2 };

var pos = array.Where(n => n > 0).OrderBy(n => n).Select(n => n);

foreach (int elm in pos) Console.WriteLine(elm);
→2, 3

OrderBy(n => n)
OrderByDescending(n => n)

select句

要素を加工して指定

int[] array = { 3, -5, -1, 0, 2 };

var pos =
 from n in array
 select Math.Abs(n) ※abs:絶対値
 select n;

foreach (int elm in pos) Console.WriteLine(elm);
→3, 5, 1, 0, 2

int[] array = { 3, -5, -1, 0, 2 };

要素を加工して指定
var pos = array.Select(n => Math.Abs(n)).OrderBy(n => n);

foreach (int elm in pos) Console.WriteLine(elm);
→0, 1, 2, 3, 5

クラス要素を指定

class MyClass
{
 public int myInt { get; private set; }
 public MyClass(int prm)
 {
  this.myInt = prm;
 }
}

static void Main(string[] args)
{

 MyClass[] myClass = {
  new MyClass(5),
  new MyClass(10),
  new MyClass(15)
 };
 
 var myInt =
  from n in myClass
  select n.myInt;
 
 foreach (var elm in myInt) Console.WriteLine(elm);
 →5, 10, 15
}

class MyClass
{
 public int myInt { get; private set; }
 public MyClass(int prm)
 {
  this.myInt = prm;
 }
}

static void Main(string[] args)
{

 MyClass[] myClass = {
  new MyClass(5),
  new MyClass(10),
  new MyClass(15)
 };
 
 var pos = myClass.Select(n => n.myInt);
 
 foreach (var elm in myInt) Console.WriteLine(elm);
 →5, 10, 15
}

別クラスのインスタンスを指定

class HerClass
{
 public int herInt { get; private set; }

 public HerClass(int prm)
 {
  this.herInt = prm*2;
 }
}

static void Main(string[] args)
{

 MyClass[] myClass = {
  new MyClass(5),
  new MyClass(10),
  new MyClass(15)
 };

var myInt =
 from n in myClass
 select new HerClass(n.myInt);

foreach (var elm in myInt) Console.WriteLine(elm.herInt);
→10, 20, 30
}

class HerClass
{
 public int herInt { get; private set; }

 public HerClass(int prm)
 {
  this.herInt = prm*2;
 }
}

static void Main(string[] args)
{

 MyClass[] myClass = {
  new MyClass(5),
  new MyClass(10),
  new MyClass(15)
 };

var pos = myClass.Select(n => new HerClass(n.myInt));

foreach (var elm in myInt) Console.WriteLine(elm.herInt);
→10, 20, 30
}

group句

string[] array = { "兵庫県", "西宮市", "尼崎市", "奈良県", "芦屋市", "神戸市", "滋賀県", "大津市", "彦根市" };

var place =
 from n in array
 group n by n.Substring(2);
 3文字目で分類

foreach (var elm in place)
{
 // 親要素.Key
 Console.WriteLine(elm.Key);

 // 子要素
 foreach (var e in elm)
 {
  Console.WriteLine(e);
 }
}


親要素.Key
兵庫県
奈良県
滋賀県
親要素.Key
西宮市
尼崎市
芦屋市
神戸市
大津市
彦根市

string[] array = { "兵庫県", "西宮市", "尼崎市", "奈良県", "芦屋市", "神戸市", "滋賀県", "大津市", "彦根市" };

var pos = array.GroupBy(n => n.Substring(2));
 3文字目で分類

foreach (var parent in pos)
 foreach (var child in parent )
  Console.WriteLine(child);


兵庫県
奈良県
滋賀県
西宮市
尼崎市
芦屋市
神戸市
大津市
彦根市

join句

select句にfrom句の要素を指定

class Item
{
 public int ItemId { get; private set; }
 public string ItemNm { get; private set; }
 
 public Item(int prmId, string prmNm)
 {
  this.ItemId = prmId;
  this.ItemNm = prmNm;
 }
}

class StockInfo
{
 public int ItemId { get; private set; }
 public bool InStock { get; private set; }
 
 public StockInfo(int prmId, bool prmInStock)
 {
  this.ItemId = prmId;
  this.InStock = prmInStock;
 }
}

static void Main(string[] args)
{

 Item[] items = {
  new Item(prmId: 1, prmNm: @”C#”),
  new Item(prmId: 2, prmNm: @”JavaScript”),
  new Item(prmId: 3, prmNm: @”C++”)
 };
 
 StockInfo[] stockInfo = {
  new StockInfo(prmId: 1, prmInStock: true),
  new StockInfo(prmId: 2, prmInStock: false),
  new StockInfo(prmId: 3, prmInStock: true)
 };
 
 var list =
  from item in items
  join info in stockInfo
   on item.ItemId equals info.ItemId
  where info.InStock == true
  select item.ItemNm;
 
 foreach (var elm in list) Console.WriteLine(elm);
}

C#
C++

select句に別クラスのインスタンスを指定

class ItemList
{
 public string ItemNm { get; private set; }
 public bool InStock { get; private set; }

 public ItemList(string prmNm, bool prmInStock)
 {
  this.ItemNm = prmNm;
  this.InStock = prmInStock;
 } 
}

static void Main(string[] args)
{

 var list =
  from item in items
  join info in stockInfo
   on item.ItemId equals info.ItemId
  select new ItemList(prmNm:item.ItemNm, prmInStock: info.InStock);

 foreach (var elm in list)
 {
  Console.WriteLine(elm.ItemNm + “:” + elm.InStock);
 }
}

C#:True
JavaScript:False
C++:True

class ItemList
{
 public string ItemNm { get; private set; }
 public bool InStock { get; private set; }

 public ItemList(string prmNm, bool prmInStock)
 {
  this.ItemNm = prmNm;
  this.InStock = prmInStock;
 } 
}

static void Main(string[] args)
{

 var list = items.Join(
  stockInfo,
  n => n.ItemId,
  m => m.ItemId,
  (n, m) => new ItemList(prmNm: n.ItemNm, prmInStock:m.InStock));
 
 foreach (var elm in list) Console.WriteLine(elm.ItemNm + ":" + elm.InStock);
}

C#:True
JavaScript:False
C++:True

select句に匿名クラスのインスタンスを指定

static void Main(string[] args)
{

 var list =
  from item in items
  join info in stockInfo
   on item.ItemId equals info.ItemId
  select new { ItemNm = item.ItemNm, InStock = info.InStock };

 foreach (var elm in list)
 {
  Console.WriteLine(elm.ItemNm + “:” + elm.InStock);
 }
}

C#:True
JavaScript:False
C++:True

static void Main(string[] args)
{

 var list = items.Join(
  stockInfo,
  n => n.ItemId,
  m => m.ItemId,
  (n, m) => new { ItemNm = n.ItemNm, InStock = m.InStock });
 
 foreach (var elm in list) Console.WriteLine(elm.ItemNm + ":" + elm.InStock);
}

C#:True
JavaScript:False
C++:True

クエリの実行タイミング

int[] array = { 3, -5, -1, 0, 2 };
var pos =
 from n in array
 where n > 0
 select n;
この時点ではクエリは実行されておらず、クエリ変数に値は格納されていない
foreach (int elm in pos) Console.WriteLine(elm);
→3, 2
array[1] *= -1;
array[2] *= -1;
データソースを変更
foreach (int elm in pos) Console.WriteLine(elm);
→3, 5, 1, 2
データソース:クエリ式が変化するとクエリ変数も変化している。

into:クエリの接続

var place =
 from n in array
 group n by n.Substring(2)
 into m
 where m.Count() <= 3
 要素数が3以下のグループに絞る
 select m;

foreach (var elm in place)
{
 foreach (var e in elm) Console.WriteLine(e);
}


兵庫県
奈良県
滋賀県

let:クエリ変数

string[] strArray = { "西宮", "尼崎", "芦屋" };

var strs =
 from n in strArray
 select n;

foreach (var elm in strs) Console.WriteLine(elm);

西宮
尼崎
芦屋

var chrs =
 from n in strArray
 let chrArray = n.ToCharArray()
 文字列型要素→char型配列 へ変換し、クエリ変数に格納
  from m in chrArray
  select m;

foreach (var elm in chrs) Console.WriteLine(elm);

西




例(2)
string[] strArray = { "兵庫県", "西宮市", "尼崎市", "奈良県", "芦屋市", "神戸市", "滋賀県", "大津市", "彦根市" };

var strs =
 from n in strArray
 let place = n.Substring(2)
 where place.Equals("県")
 select n
  into m
  select m;

foreach (var elm in strs) Console.WriteLine(elm);

兵庫県
奈良県
滋賀県