「Unity/Csharp/linq」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→条件複数行でソート(fetchAll)) |
|||
(同じ利用者による、間の36版が非表示) | |||
行2: | 行2: | ||
<pre> | <pre> | ||
using System.Linq; | using System.Linq; | ||
+ | </pre> | ||
+ | |||
+ | ==配列データの用意== | ||
+ | ===users=== | ||
+ | User.cs | ||
+ | <pre> | ||
+ | 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 = 13, name = "jiro" }); | ||
+ | users.Add(new User() { age = 12, name = "saburo" }); | ||
+ | users.Add(new User() { age = 15, name = "siro" }); | ||
+ | </pre> | ||
+ | |||
+ | ===scores=== | ||
+ | <pre> | ||
+ | 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 }); | ||
</pre> | </pre> | ||
行11: | 行53: | ||
return scores.FirstOrDefault(score => score.yyyymmdd == yyyymmdd); | return scores.FirstOrDefault(score => score.yyyymmdd == yyyymmdd); | ||
} | } | ||
+ | // 検索にひっかからないとnullが帰ってくる | ||
+ | ScoreDay score = dao.FindRowByYyyymmdd("201903"); | ||
+ | if (score == null) return; | ||
</pre> | </pre> | ||
行22: | 行67: | ||
</pre> | </pre> | ||
− | == | + | ==条件複数行でソート(fetchAll)== |
<pre> | <pre> | ||
− | + | public IOrderedEnumerable <ScoreDay> FindAllByYyyymmdd(string yyyymmdd) | |
{ | { | ||
− | + | List<ScoreDay> scores = FindAll(); | |
− | + | return scores.Where(score => score.yyyymmdd == yyyymmdd).OrderByDescending(value => value.age); | |
− | + | } | |
− | + | </pre> | |
− | } | + | |
+ | ==条件を複数指定== | ||
+ | AND条件 | ||
+ | <pre> | ||
+ | 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)); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | OR条件 | ||
+ | <pre> | ||
+ | public IOrderedEnumerable <ScoreDay> FindAllByYyyymmddOrCate(string yyyymmdd, string cate) | ||
+ | { | ||
+ | List<ScoreDay> scores = FindAll(); | ||
+ | return scores.Where(score => score.yyyymmdd == yyyymmdd || score.cate.Equals(cate)); | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | 参考:https://www.fenet.jp/dotnet/column/language/8203/ | ||
+ | |||
+ | ==順序== | ||
+ | <pre> | ||
// 年下順 | // 年下順 | ||
− | IOrderedEnumerable< | + | IOrderedEnumerable<User> orderedUsers = users.OrderBy(value => value.age); |
// 年上順 | // 年上順 | ||
− | IOrderedEnumerable< | + | IOrderedEnumerable<User> orderedDescUsers = users.OrderByDescending(value => value.age); |
+ | foreach (User user in orderedUsers) { | ||
+ | Debug.Log(user.name); | ||
+ | } | ||
</pre> | </pre> | ||
参考:https://doruby.jp/users/ino/entries/%E3%80%90C--Unity%E3%80%91LINQ%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%82%89%E3%81%A8%E3%81%A6%E3%82%82%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%81%A0%E3%81%A3%E3%81%9F | 参考:https://doruby.jp/users/ino/entries/%E3%80%90C--Unity%E3%80%91LINQ%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%82%89%E3%81%A8%E3%81%A6%E3%82%82%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%81%A0%E3%81%A3%E3%81%9F | ||
− | + | ==取得件数(limit)を絞る== | |
− | == | + | |
List<Score> scores = new List<Score>(); | List<Score> scores = new List<Score>(); | ||
IEnumerable<Score> tmpScores = scores.Skip(0).Take(100); | IEnumerable<Score> tmpScores = scores.Skip(0).Take(100); | ||
行48: | 行118: | ||
IEnumerable<Score> tmpScores = scores.Where(score => score.sec > 6); | IEnumerable<Score> tmpScores = scores.Where(score => score.sec > 6); | ||
List<Score> scores = tmpScores.ToList(); | 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をListへ変換== | ||
行59: | 行137: | ||
==like検索== | ==like検索== | ||
List<Score> scores = FindAll(); | List<Score> scores = FindAll(); | ||
− | IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.Contains("/201903/")); | + | 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前方一致== | ==like前方一致== | ||
行68: | 行151: | ||
List<Score> scores = FindAll(); | List<Score> scores = FindAll(); | ||
IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.EndsWith("0316")); | IEnumerable<Score> scores = scores.Where(record => record.yyyymmdd.EndsWith("0316")); | ||
+ | |||
+ | ==GroupByを使う場合== | ||
+ | 件数をkeyにgroupbyを行った場合 | ||
+ | <pre> | ||
+ | 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); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | 参考:https://www.sejuku.net/blog/47220 | ||
+ | |||
+ | ==最大値最小値== | ||
+ | <pre> | ||
+ | int ageMax = ages.Max(); | ||
+ | int ageMin = ages.Min(); | ||
+ | </pre> | ||
+ | |||
+ | ==条件に当てはまる件数を取得== | ||
+ | tmpScores.Where(n => n.point > 0).Count(); | ||
+ | pointが0以上であるものの件数 | ||
+ | |||
+ | ==条件に当てはまるときに値更新== | ||
+ | <pre> | ||
+ | List<User> rows = FindAll(); | ||
+ | User row = rows.Where(row => row.id == id).FirstOrDefault(); | ||
+ | row.age = age; | ||
+ | </pre> | ||
+ | |||
+ | 参考: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のサンプル== | ||
+ | <pre> | ||
+ | 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 | ||
+ | </pre> | ||
+ | |||
+ | ===同じ値を入れた場合=== | ||
+ | 以下エラーが発生する | ||
+ | <pre> | ||
+ | InvalidOperationException: Sequence contains more than one matching element | ||
+ | System.Linq.Enumerable.SingleOrDefault[TSource] | ||
+ | </pre> | ||
+ | サンプル | ||
+ | <pre> | ||
+ | |||
+ | 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); | ||
+ | </pre> | ||
+ | 参考:https://kuttsun.blogspot.com/2019/04/c-linq-first-single.html |
2024年11月25日 (月) 11:42時点における最新版
目次
準備
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 = 13, name = "jiro" }); users.Add(new User() { age = 12, name = "saburo" }); users.Add(new User() { age = 15, 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