質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.36%

C#のLINQでSQL文を文字列でわたすには

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 5,083

Unityにて絞り込み機能を作成しようと思っており、
SQL文をList型に適応したいのですが検索しても見つからず詰まってしまいました。

タイプが1~6まであり、それぞれボタンと連動しています。

ボタンはトグルになっていてタイプ1とタイプ3が選択状態であれば、
タイプ1とタイプ3に合致するデータのみを表示します。

下記のようなWHERE句をLINQに渡したいのですがどのようにしたら良いかがわかりません。
"WHERE Type == タイプ1 OR rarity == タイプ3"

●環境
Unity5.3.4
.NetFrameWork:3.5(C#3.0相当)

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

var list = new List<SampleData>();
var result = list.Where(data => data.Type == "type1" || data.Rarity == "type3");


上記のようなラムダ式による抽出を動的に行う方法です。

var parameters = Expression.Parameter(typeof(SampleData), "data");
var body = Expression.OrElse(
    Expression.Equal(Expression.PropertyOrField(parameters, "Type"), Expression.Constant("type1", typeof(string))),
    Expression.Equal(Expression.PropertyOrField(parameters, "Rarity"), Expression.Constant("type3", typeof(string))));
var lambda = Expression.Lambda<Func<SampleData, bool>>(body, parameters);
var predicate = lambda.Compile();

var list = new List<SampleData>();
var result = list.Where(data => predicate(data));

更に、選択されたボタンからbodyにあたる部分を動的に生成することで、
希望される処理が可能かと思います。

<参考>
http://www.atmarkit.co.jp/fdotnet/dotnettips/986dynamiclinq/dynamiclinq.html

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/28 16:52 編集

    ご返信ありがとうございます、
    条件が2つものに関しては下記ソースでできました。

    Expression.OrElseは2つの引数にしか対応していないようなのですが
    3つ以上あった場合はどのようにすれば良いのでしょうか?

    ```C#
    List<testClass> testClassList = new List<testClass>();

    public class testClass
    {
    public int ValInt;
    public int ValType;
    public string ValString;
    public bool ValBool1;
    public bool ValBool2;
    }


    public void OnClickButton()
    {

    for(int i = 0; i < 5; i++)
    {
    testClass testData = new testClass();
    testData.ValInt = i;
    testData.ValType = i * 2;
    testData.ValString = i.ToString();
    testData.ValBool1 = i % 2 == 0 ? true : false;
    testData.ValBool2 = i % 2 == 1 ? true : false;
    testClassList.Add(testData);
    }

    var parameters = Expression.Parameter(typeof(testClass), "data");

    var body = Expression.OrElse(
    Expression.Equal(Expression.PropertyOrField(parameters, "ValString"), Expression.Constant("2", typeof(string))),
    Expression.Equal(Expression.PropertyOrField(parameters, "ValString"), Expression.Constant("4", typeof(string))));

    var lambda = Expression.Lambda<Func<testClass, bool>>(body, parameters);
    var predicate = lambda.Compile();

    var list = new List<testClass>();
    var result = testClassList.Where(data => predicate(data));

    foreach(var data in result)
    {
    Debug.Log("ValBool1=" + data.ValBool1.ToString());
    Debug.Log("ValBool2=" + data.ValBool2.ToString());
    Debug.Log("ValInt=" + data.ValInt.ToString());
    Debug.Log("ValString=" + data.ValString);
    Debug.Log("ValType=" + data.ValType.ToString());
    }
    }
    ```

    キャンセル

  • 2016/05/28 19:32 編集

    ラムダ式右辺の各式のExpressionをA, B, Cとする場合、
    Expression.OrElse(Expression.OrElse(A, B), C)
    とすることで、
    ((A || B) || C)
    という形ではありますが3つ以上のOrElseにも対応は可能です。

    例えば、A,B,C,…の各Expressionを
    var expressions = new List<Expression>();
    として持ち、
    var body = expressions.Aggregate((x, y) => Expression.OrElse(x, y));
    などとすることで生成することが出来るのではないでしょうか。

    キャンセル

  • 2016/05/30 00:58

    例題までご提示いただきありがとうございます。

    貼り付けたソースコードの一部を下記に変更したら3つにも対応できました。

    var body = Expression.OrElse(
    Expression.Equal(Expression.PropertyOrField(parameters, "ValString"), Expression.Constant("2", typeof(string))),
    Expression.Equal(Expression.PropertyOrField(parameters, "ValString"), Expression.Constant("4", typeof(string))));

    var body1 = Expression.OrElse(
    body,
    Expression.Equal(Expression.PropertyOrField(parameters, "ValString"), Expression.Constant("0", typeof(string))));

    Aggregateがわかってなかったのでちょっと調べたのですが、
    集計してくれるというか1つにまとめてくれるもののようなので
    List内のExpressionをまとめてくれるのではと思ってます。

    デバッグで動作を見ながらbodyにまとめた結果が格納されるかチェックしてみます。

    キャンセル

+1

比較対象となるフィールド数が可変(検証するボタンの種類が可変)の場合、Linq for Objects では、対象フィールドの値だけを含んだリストを作成し、これと join することで該当するオブジェクトだけを抽出するのが良いと思います。

具体的には・・・

using System;
using System.Collections.Generic;
using System.Linq;

class A {
    public string Name;
    public int Type;
    public A(string n, int t) {
        Name = n;
        Type = t;
    }
}

class MainClass {
    static void Main() {
        int[] type_array = {2,4};
        A[] a_array = {
          new A("name1-1", 1),
          new A("name1-2", 1),
          new A("name2-1", 2),
          new A("name2-2", 2),
          new A("name2-3", 2),
          new A("name3-1", 3),
          new A("name4-1", 4),
          new A("name4-2", 4),
          new A("name4-3", 4),
          new A("name5-1", 5),
          new A("name5-2", 5)
        };

        var result =
            from a in a_array
            join t in type_array on a.Type equals t
            select a;

        foreach(var a in result) {
            Console.WriteLine("Name = " + a.Name);
        }
    }
}

// 出力
// Name = name2-1
// Name = name2-2
// Name = name2-3
// Name = name4-1
// Name = name4-2
// Name = name4-3

このように書くことができます。 このサンプルコードでは type_array 配列の内容が変化しても、該当するオブジェクトを抽出できます。

ご参考になれば。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る