web-dev-qa-db-ja.com

Contains(string)の代わりにLINQ Contains(string [])を使用する方法

一つ大きな質問がありました。

Linqクエリを取得して、次のようにします。

from xx in table
where xx.uid.ToString().Contains(string[])
select xx

string[]配列の値は、(1,45,20,10など)のような数字になります

.Containsのデフォルトは.Contains(string)です。

代わりにこれを行う必要があります:.Contains(string[])...

EDIT: 1人のユーザーがstring[]の拡張クラスを作成することを提案しました。方法を学びたいのですが、私を正しい方向に向けてくれる人はいますか?

EDIT: uidも数値になります。それが文字列に変換される理由です。

誰か助けて?

85

spoulsonはほぼ適切ですが、最初にList<string>からstring[]を作成する必要があります。実際、uidがintである場合は、List<int>の方が適しています。 List<T>Contains()をサポートします。 uid.ToString().Contains(string[])を実行すると、文字列としてのuidが部分文字列として配列のすべての値を含むことを意味しますか?拡張メソッドを作成したとしても、その意味は間違っています。

[編集]

Mitch Wheatが示すように、変更してstring[]に変更しない限り、変換ステップをスキップできます。

[ENDEDIT]

拡張メソッドを実行しない場合(潜在的なuidのコレクションがintとして既にない場合は、代わりにList<int>()を使用するだけです)、これが目的です。これは連鎖メソッド構文を使用しますが、これはよりクリーンだと思い、より多くのプロバイダーでクエリを使用できるようにintに変換します。

var uids = arrayofuids.Select(id => int.Parse(id)).ToList();

var selected = table.Where(t => uids.Contains(t.uid));
76
tvanfosson

本当にレプリケートしたい場合Containsが、配列の場合、 拡張方法 と使用例のコードがあります:

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

namespace ContainsAnyThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            string testValue = "123345789";

            //will print true
            Console.WriteLine(testValue.ContainsAny("123", "987", "554")); 

            //but so will this also print true
            Console.WriteLine(testValue.ContainsAny("1", "987", "554"));
            Console.ReadKey();

        }
    }

    public static class StringExtensions
    {
        public static bool ContainsAny(this string str, params string[] values)
        {
            if (!string.IsNullOrEmpty(str) || values.Length > 0)
            {
                foreach (string value in values)
                {
                    if(str.Contains(value))
                        return true;
                }
            }

            return false;
        }
    }
}
31
Jason Jackson

以下を試してください。

string input = "someString";
string[] toSearchFor = GetSearchStrings();
var containsAll = toSearchFor.All(x => input.Contains(x));
17
JaredPar

.NET 4.0のLINQには別のオプションがあります。 .Any()メソッド;

string[] values = new[] { "1", "2", "3" };
string data = "some string 1";
bool containsAny = values.Any(data.Contains);
15
RJ Lohan

または、既にリストにデータがあり、他のLinq形式を好む場合:)

List<string> uids = new List<string>(){"1", "45", "20", "10"};
List<user> table = GetDataFromSomewhere();

List<user> newTable = table.Where(xx => uids.Contains(xx.uid)).ToList();
6
JumpingJezza

どうですか:

from xx in table
where stringarray.Contains(xx.uid.ToString())
select xx
3
spoulson

これは遅い答えですが、私はそれがまだ有用であると信じています
この問題を解決するのに役立つ NinjaNye.SearchExtension nugetパッケージを作成しました。

string[] terms = new[]{"search", "term", "collection"};
var result = context.Table.Search(terms, x => x.Name);

複数の文字列プロパティを検索することもできます

var result = context.Table.Search(terms, x => x.Name, p.Description);

または、検索語が出現した回数を示すプロパティを単に含むIQueryable<IRanked<T>>を返すRankedSearchを実行します。

//Perform search and rank results by the most hits
var result = context.Table.RankedSearch(terms, x => x.Name, x.Description)
                     .OrderByDescending(r = r.Hits);

プロジェクトのGitHubページには、より広範なガイドがあります。 https://github.com/ninjanye/SearchExtensions

これが将来の訪問者に役立つことを願っています

2
NinjaNye

これは、拡張メソッドを記述する1つの方法の例です(注:非常に大きな配列にはこれを使用しません。別のデータ構造がより適切です...):

namespace StringExtensionMethods
{
    public static class StringExtension
    {
        public static bool Contains(this string[] stringarray, string pat)
        {
            bool result = false;

            foreach (string s in stringarray)
            {
                if (s == pat)
                {
                    result = true;
                    break;
                }
            }

            return result;
        }
    }
}
2
Mitch Wheat

Linq拡張メソッド。 IEnumerableオブジェクトで動作します。

    public static bool ContainsAny<T>(this IEnumerable<T> Collection, IEnumerable<T> Values)
    {
        return Collection.Any(x=> Values.Contains(x));
    }

使用法:

string[] Array1 = {"1", "2"};
string[] Array2 = {"2", "4"};

bool Array2ItemsInArray1 = List1.ContainsAny(List2);
1
kravits88

このようなこともできると思います。

from xx in table
where (from yy in string[] 
       select yy).Contains(xx.uid.ToString())
select xx
1
ctrlShiftBryan
var SelecetdSteps = Context.FFTrakingSubCriticalSteps
             .Where(x => x.MeetingId == meetid)
             .Select(x =>    
         x.StepID  
             );

        var crtiticalsteps = Context.MT_CriticalSteps.Where(x =>x.cropid==FFT.Cropid).Select(x=>new
        {
            StepID= x.crsid,
            x.Name,
            Checked=false

        });


        var quer = from ax in crtiticalsteps
                   where (!SelecetdSteps.Contains(ax.StepID))
                   select ax;
0
Hari Lakkakula

試してください:

var stringInput = "test";
var listOfNames = GetNames();
var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower());
select names;
0
Hedego

それでは、uidが一意の識別子(Guid)であると正しく仮定していますか?これは可能なシナリオの単なる例ですか、それとも文字列の配列に一致するGUIDを実際に見つけようとしていますか?

これが本当なら、このアプローチ全体を本当に再考したいと思うかもしれませんが、これは本当に悪い考えのようです。 GuidをGuidに一致させようとしているはずです

Guid id = new Guid(uid);
var query = from xx in table
            where xx.uid == id
            select xx;

「含む」を使用して文字列配列をGuidのコンテンツに一致させるのが良いアイデアになるシナリオを正直に想像することはできません。 1つには、Contains()はGUID内の数字の順序を保証しないため、複数のアイテムと一致する可能性があります。この方法でGUIDを比較することは言うまでもなく、単に直接行うよりもはるかに遅くなります。

0
justin.m.chase

私が見つけた最良の解決策は、次のような結果を生成するSQLでテーブル値関数を作成することです。

CREATE function [dbo].[getMatches](@textStr nvarchar(50)) returns @MatchTbl table(
Fullname nvarchar(50) null,
ID nvarchar(50) null
)
as begin
declare @SearchStr nvarchar(50);
set @SearchStr = '%' + @textStr + '%';
insert into @MatchTbl 
select (LName + ', ' + FName + ' ' + MName) AS FullName, ID = ID from employees where LName like @SearchStr;
return;
end

GO

select * from dbo.getMatches('j')

次に、関数をLINQ.dbmlデザイナーにドラッグし、他のオブジェクトと同じように呼び出します。 LINQは、保存された関数の列も認識しています。このように呼び出します::

Dim db As New NobleLINQ
Dim LNameSearch As String = txt_searchLName.Text
Dim hlink As HyperLink

For Each ee In db.getMatches(LNameSearch)
   hlink = New HyperLink With {.Text = ee.Fullname & "<br />", .NavigateUrl = "?ID=" & ee.ID}
   pnl_results.Controls.Add(hlink)
Next

信じられないほどシンプルで、アプリケーションのSQLとLINQのパワーを最大限に活用しています...そして、もちろん、同じ効果のために必要なテーブル値関数を生成できます!

0
beauXjames

本当にやりたいのは、2つのデータベースがあり、共通の製品テーブルがあるシナリオを想像してみてください。また、IDが「B」と共通のテーブル「A」から製品を選択したい

メソッドcontainsを使用するのは複雑すぎて、これを行うには交差点があり、そのための交差点と呼ばれるメソッドがあります

msdnの例: http://msdn.Microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

int [] numbers =(0、2、4、5、6、8、9); int [] numbersB =(1、3、5、7、8); var = commonNumbers numbersA.Intersect(numbersB);

必要なものは交差点で簡単に解決できると思います

0
Lucas Cria
from xx in table
where xx.uid.Split(',').Contains(string value )
select xx
0
user1119399

特権ユーザーIDリストにテーブルのその行のIDが含まれていることを確認して、逆の方法で記述する必要があります。

string[] search = new string[] { "2", "3" };
var result = from x in xx where search.Contains(x.uid.ToString()) select x;

LINQはここでは非常に明るく動作し、適切なSQLステートメントに変換します。

sp_executesql N'SELECT [t0].[uid]
FROM [dbo].[xx] AS [t0]
WHERE (CONVERT(NVarChar,[t0].[uid]))
IN (@p0, @p1)',N'@p0 nvarchar(1),
@p1 nvarchar(1)',@p0=N'2',@p1=N'3'

基本的に「search」配列の内容をsqlクエリに埋め込み、SQLの「IN」キーワードでフィルタリングを行います。

0
Gorkem Pacaci

この拡張方法を確認してください。

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

namespace ContainsAnyProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            const string iphoneAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like...";

            var majorAgents = new[] { "iPhone", "Android", "iPad" };
            var minorAgents = new[] { "Blackberry", "Windows Phone" };

            // true
            Console.WriteLine(iphoneAgent.ContainsAny(majorAgents));

            // false
            Console.WriteLine(iphoneAgent.ContainsAny(minorAgents));
            Console.ReadKey();
        }
    }

    public static class StringExtensions
    {
        /// <summary>
        /// Replicates Contains but for an array
        /// </summary>
        /// <param name="str">The string.</param>
        /// <param name="values">The values.</param>
        /// <returns></returns>
        public static bool ContainsAny(this string str, params string[] values)
        {
            if (!string.IsNullOrEmpty(str) && values.Length > 0)
                return values.Any(str.Contains);

            return false;
        }
    }
}
0
ron.camaron

私は解決策を見つけることができましたが、DBからすべての結果を返すAsEnumerable()を使用する必要があるため、素晴らしい解決策ではありませんでした。 。

var users = from u in (from u in ctx.Users
                       where u.Mod_Status != "D"
                       select u).AsEnumerable()
            where ar.All(n => u.FullName.IndexOf(n,
                        StringComparison.InvariantCultureIgnoreCase) >= 0)
            select u;

元の投稿が続きます:

どのように逆をしますか?エンティティフレームワークで次のようなことをしたいです。

string[] search = new string[] { "John", "Doe" };
var users = from u in ctx.Users
            from s in search
           where u.FullName.Contains(s)
          select u;

私が欲しいのは、FullNameに「search」のすべての要素が含まれるすべてのユーザーを検索することです。私はいくつかの異なる方法を試しましたが、それらはすべて私のために働いていませんでした。

私も試しました

var users = from u in ctx.Users select u;
foreach (string s in search) {
    users = users.Where(u => u.FullName.Contains(s));
}

このバージョンでは、検索配列の最後の要素を含むもののみが検索されます。

0
Brett Ryan