[C#] 28. リスト(List)とディクショナリ(Dictionary)、そしてLinq式を使い方
こんにちは。明月です。
この投稿はC#のリスト(List)とディクショナリ(Dictionary)、そしてLinq式を使い方に関する説明です。
以前の投稿で配列とオブジェクト指向プログラミング(OOP)に関して説明したことがあります。에 대해서 설명한 적이 있습니다.
link - [C#] 8. 配列とリスト
link - [C#] 20. オブジェクト指向プログラミング(OOP)の4つの原則(カプセル化、抽象化、継承化、多相化(ポリモーフィズム))
オブジェクト指向プログラミング(OOP)に関して簡単に改めて説明するとプログラムを開発する時、すべてをオブジェクト(Object)に考えて開発することという意味です。
つまり、オブジェクトというのはプログラムでクラス(Class)の形で管理すること、またはこのオブジェクトを効果的に管理するためにリスト(List)とディクショナリ(Dictionary)をよく使います。
リストはデータ構造アルゴリズムでは連結リストアルゴリズムだし、ディクショナリ(Dictionary)はマップアルゴリズムです。
連結リストのアルゴリズムは始めから最後までのデータをポインタで連結したことだし、ディクショナリはキーと値で連結したデータ構造です。
using System;
using System.Collections.Generic;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// リスト宣言(リストのオブジェクトはNodeクラス)
var list = new List<Node>();
// iが0から9まで繰り返し
for (int i = 0; i < 10; i++)
{
// リストにデータを挿入
list.Add(new Node(i));
}
// リストの5番目のNodeインスタンスを取得
var removeNode = list[5];
// リストから取り除く。
list.Remove(removeNode);
// リストの2番目にDataが100のNodeインスタンスを挿入
list.Insert(2, new Node(100));
// listの値を順番とおりに出力
foreach (var node in list)
{
// コンソール出力
Console.WriteLine(node.Data);
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
リストから0の値から9までのDataを持っているNodeインスタンスを順番とおりに格納されています。
リストは確実に順番が決めているし、5番目のNodeインスタンスを取得してリストから取り除きました。
そして、2番目のリストに100のDataを持っているNodeインスタンスを挿入しました。
これかリストの特性です。
ディクショナリ(Dictionary)の場合は始めから最後までの順番が決めていることではなく、Keyからデータを取得します。
using System;
using System.Collections.Generic;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// ディクショナリ宣言(ディクショナリのキーはString、オブジェクトはNodeクラス)
var dic = new Dictionary<string, Node>();
// iが0から9まで繰り返し。
for (int i = 0; i < 10; i++)
{
// ディクショナリのキーは"Key" + iの値でデータを挿入。
dic.Add("Key" + i, new Node(i));
}
// ディクショナリのキーがKey2の値を取り除く。
dic.Remove("Key2");
// ディクショナリのキーがkey100のデータを挿入。
dic.Add("key100", new Node(100));
// ディクショナリのKeyを取得して個数ほど繰り返し。
foreach (var key in dic.Keys)
{
// ディクショナリのKeyの値でデータを取得
var node = dic[key];
// コンソール出力
Console.WriteLine("Key = " + key + ", value = " + node.Data);
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
ディクショナリのKeyを通ってデータを入力して取り除く、出力しました。
リストと違うのはデータが順番とおりにあることではなく、keyというデータを通ってデータが管理することを確認できます。
参考でKeyの値はリストの形式で順番とおりに格納されていることではなく、Keysでキーのリスト(?)を取得するとリストが順番とおりではないことを確認できます。
C#はオブジェクト指向プログラム言語(OOP)としてデータを管理するためにリストとディクショナリをたくさん使います。
リストで上の例みたいに入力、出力することができますが、特定データを検索するために我々は繰り返しを使います。
using System;
using System.Collections.Generic;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// リスト宣言(リストのオブジェクトはNodeクラス)
var list = new List<Node>();
// iが0から9まで繰り返し
for (int i = 0; i < 10; i++)
{
// リストにデータを挿入
list.Add(new Node(i));
}
// 偶数の値だけ他のリストで格納する。
var evenList = new List<Node>();
// listの値を順番とおりに出力
foreach (var node in list)
{
// nodeインスタンスのDataが偶数の場合
if (node.Data % 2 == 0)
{
// リストに格納
evenList.Add(node);
}
}
// evenListの値を順番とおりに出力
foreach (var node in evenList)
{
// コンソール出力
Console.WriteLine(node.Data);
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
listのデータの値が偶数のデータを検索してevenListのリストにインスタンスを格納しました。
そしてevenListを繰り返しで出力すると結果は0が含めている偶数だけ出力することを確認できます。
上の例は間違いソースではありませんが、C#ではもっと効率的にフィルター、抽出する方法があります。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// リスト宣言(リストのオブジェクトはNodeクラス)
var list = new List<Node>();
// iが0から9まで繰り返し
for (int i = 0; i < 10; i++)
{
// リストにデータを挿入
list.Add(new Node(i));
}
// 偶数の値だけ他のリストに格納する。
var evenList = from node in list where node.Data % 2 == 0 select node;
// evenListの値を順番とおりに出力
foreach (var node in evenList)
{
// コンソール出力
Console.WriteLine(node.Data);
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上の例はデータベースのSQLクエリみたいなプログラム式があります。
from node in list는 listの意味は各アイテムの値をnodeに置換して、whereの条件式でnode.Dataが偶数でフィルターしてselectで出力して新しいリストを生成しました。
そしてforeachで出力すると結果は上の例と同じ値を出力しました。
上みたいなプログラム式をC#ではLinqクエリ式だといいます。
リンククエリ式は上みたいにフィルター(where)の役割もありますが、整列と集合の式もあります。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// リスト宣言(リストのオブジェクトはNodeクラス)
var list = new List<Node>();
// iが0から9まで繰り返し
for (int i = 0; i < 10; i++)
{
// リストにデータを挿入
list.Add(new Node(i));
}
// 偶数、奇数別でグループを分けてそのキーでNodeを再整列する。
var filerList = from node in list orderby node.Data descending group node by node.Data % 2 into g select (key: g.Key, value: g);
// filerListのキーの順番とおりに繰り返し
foreach (var item in filerList)
{
// 各キーの中でリストを出力する。
foreach (var value in item.value)
{
// コンソール出力
Console.WriteLine("Key : " + item.key + " Value : " + value.Data);
}
// 改行
Console.WriteLine();
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
上の例ではorderbyでリストを降順(descending)で再整列してgroup byで1と0で再整列してselectでディクショナリの形でデータを生成します。
簡単にDictionary<int, List<Node>>の形で再構成することです。
プログラム設計によりデータベースクエリ式みたいに作られますが、他の方式でプログラム関数式で作成することもできます。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Example
{
// 例クラス
class Node
{
// 値をコンストラクタで格納する。
public Node(int data)
{
// プロパティのDataに値を格納
this.Data = data;
}
// Dataプロパティ
public int Data
{
// 入力はコンストラクタから受け取る。
get; private set;
}
}
class Program
{
// 実行関数
static void Main(string[] args)
{
// リスト宣言(リストのオブジェクトはNodeクラス)
var list = new List<Node>();
// iが0から9まで繰り返し
for (int i = 0; i < 10; i++)
{
// リストにデータを挿入
list.Add(new Node(i));
}
// 偶数の値だけに他のリストで格納する。
var evenList = list.Where(x => x.Data % 2 == 0);
// evenListの値を順番とおりに出力
foreach (var node in evenList)
{
// コンソール出力
Console.WriteLine(node.Data);
}
// 改行
Console.WriteLine();
// 偶数、奇数別にグループを分けて、そのキーでNodeを再整列する。
var filerList = list.OrderByDescending(x => x.Data).GroupBy(x => x.Data % 2).Select(x => (key: x.Key, value: x));
// filerListのキー順番で繰り返し
foreach (var item in filerList)
{
// 各キーの中でリストを出力する。
foreach (var value in item.value)
{
// コンソール出力
Console.WriteLine("Key : " + item.key + " Value : " + value.Data);
}
// 改行
Console.WriteLine();
}
// 任意のキーを押してください
Console.WriteLine("Press any key...");
Console.ReadLine();
}
}
}
プログラムの関数みたいにリストのフィルダーを作られます。
結果は上のクエリ式と同じ結果が出力します。
C#にはオブジェクトをリスト(List)とディクショナリ(Dictionary)でオブジェクト(Object)を管理してLinqのクエリ式と関数式を通ってデータをフィルター、分類して使います。
Linq式には代表的に一番よく使うのはwhereとselectですが、仕様により二つのリストを合体(Join)、重複データの取り除く(Distinct)、合集合(Union)などの機能があります。
少し、もっと詳細のは他の投稿で説明します。
ここまでC#のリスト(List)とディクショナリ(Dictionary)、そしてLinq式を使い方に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [C#] 35. 文字列クラス、StringとStringBuilderを使い方2019/07/22 23:15:42
- [C#] 34. 最上位クラス(Object クラス)2019/07/20 02:27:23
- [C#] 33. 匿名形式(Anonymous Types)を使い方2019/07/20 02:22:03
- [C#] 32. ジェネリックタイプ(Generic Type)を使い方2019/07/18 22:50:16
- [C#] 31. アトリビュート(Attribute)を使い方2019/07/18 20:22:16
- [C#] 30. Linq関数式を使う方法2019/07/17 23:06:42
- [C#] 29. Linqクエリ式を使い方2019/07/17 20:57:00
- [C#] 28. リスト(List)とディクショナリ(Dictionary)、そしてLinq式を使い方2019/07/16 22:40:03
- [C#] 27. varキーワードとdynamicキーワード2019/07/16 20:41:27
- [C#] 26. 例外処理(try ~ catch)する方法2019/07/16 00:59:34
- [C#] 25. イベント(event)キーワードを使い方2019/07/16 00:48:03
- [C#] 24. ラムダ式(匿名関数)とAction、Func関数を使い方、そしてクロージャ(Closure)2019/07/16 00:36:19
- [C#] 23. デリゲート(delegate)2019/07/15 02:25:26
- [C#] 22. インデクサー(indexer)を使う方法2019/07/13 01:06:04
- [C#] 21. C#のプロパティ(Property)2019/07/13 00:56:20
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07