Unity/Csharp/linq
提供: 初心者エンジニアの簡易メモ
目次
- 1 準備
- 2 配列データの用意
- 3 条件一行だけ(fetchRow)
- 4 条件複数行(fetchAll)
- 5 条件複数行でソート(fetchAll)
- 6 条件を複数指定
- 7 順序
- 8 取得件数(limit)を絞る
- 9 指定条件だけに絞る
- 10 条件に引っかからなかった時
- 11 IEnumerableをListへ変換
- 12 数値の合計
- 13 like検索
- 14 like前方一致
- 15 like後方一致
- 16 GroupByを使う場合
- 17 最大値最小値
- 18 条件に当てはまる件数を取得
- 19 条件に当てはまるときに値更新
- 20 ランダム順序
- 21 SingleOrDefaultのサンプル
- 22 selectで取得した値を更新したとき、全体は更新される?
- 23 削除処理
準備
using System.Linq;
配列データの用意
users
User.cs
using System;
[Serializable]
public class User
{
[SerializeField]
public int age;
[SerializeField]
public string name;
}
List<User> users = new List<User>();
users.Add(new User() { age = 10, name = "taro" });
users.Add(new User() { age = 9, name = "jiro" });
users.Add(new User() { age = 8, name = "saburo" });
users.Add(new User() { age = 7, name = "siro" });
scores
Score.cs
[Serializable]
public class Score
{
[SerializeField]
public string yyyymmdd;
[SerializeField]
public int missCnt;
[SerializeField]
public int finishCnt;
}
List<Score> scores = new List<Score>();
scores.Add(new Score() { yyyymmdd = "20190316", missCnt = 10, finishCnt = 1 });
scores.Add(new Score() { yyyymmdd = "20190315", missCnt = 13, finishCnt = 2 });
scores.Add(new Score() { yyyymmdd = "20190314", missCnt = 12, finishCnt = 3 });
scores.Add(new Score() { yyyymmdd = "20190313", missCnt = 15, finishCnt = 4 });
条件一行だけ(fetchRow)
public ScoreDay FindRowByYyyymmdd(string yyyymmdd)
{
List<ScoreDay> scores = FindAll();
return scores.FirstOrDefault(score => score.yyyymmdd == yyyymmdd);
}
// 検索にひっかからないとnullが帰ってくる
ScoreDay score = dao.FindRowByYyyymmdd("201903");
if (score == null) return;
条件複数行(fetchAll)
public IEnumerable<ScoreDay> FindAllByYyyymmdd(string yyyymmdd)
{
List<ScoreDay> scores = FindAll();
return scores.Where(score => score.yyyymmdd == yyyymmdd);
}
条件複数行でソート(fetchAll)
public IOrderedEnumerable <ScoreDay> FindAllByYyyymmdd(string yyyymmdd)
{
List<ScoreDay> scores = FindAll();
return scores.Where(score => score.yyyymmdd == yyyymmdd).OrderByDescending(value => value.age);
}
条件を複数指定
AND条件
public IOrderedEnumerable <ScoreDay> FindAllByYyyymmddAndCate(string yyyymmdd, string cate)
{
List<ScoreDay> scores = FindAll();
return scores.Where(score => score.yyyymmdd == yyyymmdd).Where(score => score.cate.Equals(cate));
}
OR条件
public IOrderedEnumerable <ScoreDay> FindAllByYyyymmddOrCate(string yyyymmdd, string cate)
{
List<ScoreDay> scores = FindAll();
return scores.Where(score => score.yyyymmdd == yyyymmdd || score.cate.Equals(cate));
}
参考:https://www.fenet.jp/dotnet/column/language/8203/
順序
// 年下順
IOrderedEnumerable<User> orderedUsers = users.OrderBy(value => value.age);
// 年上順
IOrderedEnumerable<User> orderedDescUsers = users.OrderByDescending(value => value.age);
foreach (User user in orderedUsers) {
Debug.Log(user.name);
}
取得件数(limit)を絞る
List<Score> scores = new List<Score>(); IEnumerable<Score> tmpScores = scores.Skip(0).Take(100);
指定条件だけに絞る
List<ScoreDay> scores = FindAll(); IEnumerable<Score> tmpScores = scores.Where(score => score.sec > 6); List<Score> scores = tmpScores.ToList();
条件に引っかからなかった時
List<ScoreDay> scores = FindAll();
IEnumerable<Score> tmpScores = scores.Where(score => score.sec > 6);
if (!tmpScores.Any()) {
return 0;
}
IEnumerableをListへ変換
IEnumerable<Score> tmpScores = // 略・・・ List<Score> scores = tmpScores.ToList());
数値の合計
List<Score> scores = FindAll(); return scores.Sum(record => record.missCnt);
like検索
List<Score> scores = FindAll();
IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.Contains("201903"));
// .Contains("/201903/")); // こういうスラッシュはいらない
likeしたあとの合計
IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.Contains("201903"));
Debug.Log("sum=" + scores.Sum(record => record.missCnt));
like前方一致
List<Score> scores = FindAll();
IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.StartsWith("201903"));
like後方一致
List<Score> scores = FindAll();
IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.EndsWith("0316"));
GroupByを使う場合
件数をkeyにgroupbyを行った場合
public IEnumerable<IGrouping<int ,User>>FindAllGroupByIdOrderByCntDesc()
{
List<User> users = FindAll();
return users
.GroupBy(value => value.id)
.OrderByDescending(value => value.Count());
}
List<IGrouping<int, User>> groups = FindAllGroupByIdOrderByCntDesc.FindAllGroupByIdOrderByCntDesc().ToList();
if (groups != null && groups.Count > 0)
{
foreach (IGrouping<int, User> users in groups)
{
Debug.Log("key=" + users.Key);
User user = new User();
foreach (User tmpUser in users)
{
user = tmpUser;
}
if (users.Count() == 0)
{
continue;
}
Debug.Log(user.name);
}
}
参考:https://www.sejuku.net/blog/47220
最大値最小値
int ageMax = ages.Max(); int ageMin = ages.Min();
条件に当てはまる件数を取得
tmpScores.Where(n => n.point > 0).Count();
pointが0以上であるものの件数
条件に当てはまるときに値更新
List<User> rows = FindAll(); User row = rows.Where(row => row.id == id).FirstOrDefault(); row.age = age;
参考:https://dk521123.hatenablog.com/entry/18957041
ランダム順序
List<User> users = rows.OrderBy(i => Guid.NewGuid()).Take(10).ToList();
参考:https://hacchi-man.hatenablog.com/entry/2020/05/15/220000
SingleOrDefaultのサンプル
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;
public class SingleOrDefaultScene : MonoBehaviour
{
[Serializable]
public class User
{
[SerializeField]
public int age;
[SerializeField]
public string name;
}
void Start()
{
List<User> users = new List<User>();
users.Add(new User() { age = 10, name = "taro" });
users.Add(new User() { age = 13, name = "jiro" });
User user = users.SingleOrDefault(user => user.name == "taro");
Debug.Log(user.age); // 13
同じ値を入れた場合
以下エラーが発生する
InvalidOperationException: Sequence contains more than one matching element System.Linq.Enumerable.SingleOrDefault[TSource]
サンプル
void Start()
{
List<User> users = new List<User>();
users.Add(new User() { age = 10, name = "taro" });
users.Add(new User() { age = 13, name = "jiro" });
users.Add(new User() { age = 13, name = "jiro" });
User user = users.SingleOrDefault(user => user.name == "jiro");
Debug.Log(user.age);
参考:https://kuttsun.blogspot.com/2019/04/c-linq-first-single.html
selectで取得した値を更新したとき、全体は更新される?
[Serializable]
public class User
{
[SerializeField]
public int age;
[SerializeField]
public string name;
}
void Start()
{
List<User> users = new List<User>();
users.Add(new User() { age = 10, name = "taro" });
users.Add(new User() { age = 9, name = "jiro" });
users.Add(new User() { age = 8, name = "saburo" });
User user = users?.Where(x => x != null && x.name == "taro")?.FirstOrDefault();
user.age = 100;
Debug.Log("name=" + user.name + " age=" + user.age);
foreach (User tmpUser in users)
{
Debug.Log("tmpUser.name=" + tmpUser.name + " age=" + tmpUser.age);
}
}
出力
name=taro age=100 tmpUser.name=taro age=100 tmpUser.name=jiro age=9 tmpUser.name=saburo age=8
更新された。
削除処理
users.RemoveAll(user => user.age == 9);
年齢が9のuserを削除
