facebook twitter hatena line email

「Unity/Csharp/linq」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(IEnumerableをListへ変換)
(条件複数行でソート(fetchAll))
 
(同じ利用者による、間の44版が非表示)
行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>
User[] users = new User[]
+
public IOrderedEnumerable <ScoreDay> FindAllByYyyymmdd(string yyyymmdd)
 
{
 
{
            new User() { age = 10, name = "taro" },
+
    List<ScoreDay> scores = FindAll();
            new User() { age = 13, name = "jiro" },
+
    return scores.Where(score => score.yyyymmdd == yyyymmdd).OrderByDescending(value => value.age);
            new User() { age = 12, name = "saburo" },
+
}
            new User() { age = 15, name = "siro" },
+
</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<Parameter>   orderedUsers   = users.OrderBy( value => value.age );
+
IOrderedEnumerable<User> orderedUsers = users.OrderBy(value => value.age);
 
// 年上順
 
// 年上順
IOrderedEnumerable<Parameter>   orderedUsers  = users.OrderByDescending( value => value.age );
+
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);
 +
 +
==指定条件だけに絞る==
 +
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をListへ変換==
 
  IEnumerable<Score> tmpScores = //  略・・・
 
  IEnumerable<Score> tmpScores = //  略・・・
 
  List<Score> scores = tmpScores.ToList());
 
  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を行った場合
 +
<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);
}

参考: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>();
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