我如何使用LINQ Contains(string )而不是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[])
…
编辑:一个用户build议写string[]
的扩展类。 我想学习如何,但是任何人都愿意把我指向正确的方向?
编辑: uid也是一个数字。 这就是为什么它被转换成一个string。
帮助任何人?
spoulson几乎是正确的,但是你需要首先从string[]
创build一个List<string>
。 其实一个List<int>
会更好,如果uid也是int
。 List<T>
支持Contains()
。 做uid.ToString().Contains(string[])
意味着作为一个string的uid包含数组的所有值作为子string? 即使你写了扩展方法,它的感觉也是错误的。
[编辑]
除非你像Mitch Wheat所说的那样把它改写成string[]
,那么你就可以跳过转换步骤。
[EndEdit中]
这里是你想要的,如果你没有做扩展方法(除非你已经有潜在的用户集合作为整数 – 那么就用List<int>()
来代替)。 这使用链式方法的语法,我认为是更清洁,并进行转换为int,以确保查询可以用于更多的提供者。
var uids = arrayofuids.Select(id => int.Parse(id)).ToList(); var selected = table.Where(t => uids.Contains(t.uid));
如果您真的想要复制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; } } }
尝试以下。
string input = "someString"; string[] toSearchFor = GetSearchStrings(); var containsAll = toSearchFor.All(x => input.Contains(x));
.NET 4.0中的LINQ为您提供了另一种select; .Any()方法;
string[] values = new[] { "1", "2", "3" }; string data = "some string 1"; bool containsAny = values.Any(data.Contains);
或者,如果你已经有一个列表中的数据,而且更喜欢其他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();
怎么样:
from xx in table where stringarray.Contains(xx.uid.ToString()) select xx
这是写一个扩展方法的一种方法的例子(注意:我不会使用这个非常大的数组;另一个数据结构会更合适…):
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; } } }
这是一个迟到的答案,但我相信它仍然有用 。
我创build了NinjaNye.SearchExtension nuget包,可以帮助解决这个问题:
string[] terms = new[]{"search", "term", "collection"}; var result = context.Table.Search(terms, x => x.Name);
您也可以search多个string属性
var result = context.Table.Search(terms, x => x.Name, p.Description);
或者执行一个返回IQueryable<IRanked<T>>
的RankedSearch
,它只是包含一个显示search条件出现次数的属性:
//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
希望这有助于未来的游客
我相信你也可以做这样的事情。
from xx in table where (from yy in string[] select yy).Contains(xx.uid.ToString()) select xx
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);
那么我是否正确地假设uid是唯一标识符(Guid)? 这只是一个可能的场景的例子,或者你真的想要find一个匹配string数组的GUID?
如果这是真的,你可能想重新考虑这个方法,这似乎是一个非常糟糕的主意。 你可能应该试图把Guid和Guid相匹配
Guid id = new Guid(uid); var query = from xx in table where xx.uid == id select xx;
我真的不能想象一个场景,在Guid的内容中使用“contains”来匹配string数组是一个好主意。 一方面,Contains()不能保证Guid中的数字顺序,所以你可能会匹配多个项目。 更不用说比较guid这种方式会比直接做的慢。
你应该反过来写它,检查你的priviliged用户ID列表包含该行的表上的ID:
string[] search = new string[] { "2", "3" }; var result = from x in xx where search.Contains(x.uid.ToString()) select x;
LINQ在这里performance得相当好,并将其转换为一个好的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'数组的内容embedded到sql查询中,并在SQL中用'IN'关键字进行过滤。
我设法find一个解决scheme,但不是一个伟大的,因为它需要使用AsEnumerable()这将返回从数据库中的所有结果,幸运的是,我只有1Klogging在表中,所以它不是真正知名的,但在这里。
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;
我原来的post如下:
你如何做相反的事情? 我想在entity framework中做如下的事情。
string[] search = new string[] { "John", "Doe" }; var users = from u in ctx.Users from s in search where u.FullName.Contains(s) select u;
我想要的是find所有的用户,其FullName包含“search”中的所有元素。 我尝试了很多不同的方法,所有这些方法都没有为我工作。
我也试过了
var users = from u in ctx.Users select u; foreach (string s in search) { users = users.Where(u => u.FullName.Contains(s)); }
该版本仅查找包含search数组中最后一个元素的那些版本。
我find的最好的解决scheme是继续前进,并在SQL中创build一个Table-Valued函数来产生结果,例如::
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.dbmldevise器中,然后像调用其他对象那样调用它。 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的力量…当然,您可以生成任何表值的function,你想要的相同的效果!
我相信你真正想要做的是:让我们想象一下,你有两个数据库的情况下,他们有一个共同的产品表你要从表中select“A”的产品,ID与“B”
使用这个方法包含的过于复杂,我们正在做的是一个十字路口,还有一个叫做十字路口的方法
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);
我觉得你所需要的是很容易解决的交集
检查这个扩展方法:
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; } } }
from xx in table where xx.uid.Split(',').Contains(string value ) select xx
尝试:
var stringInput = "test"; var listOfNames = GetNames(); var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower()); select names;
string[] stringArray = {1,45,20,10}; from xx in table where stringArray.Contains(xx.uid.ToString()) select xx
Dim stringArray() = {"Pink Floyd", "AC/DC"} Dim inSQL = From alb In albums Where stringArray.Contains(alb.Field(Of String)("Artiste").ToString()) Select New With { .Album = alb.Field(Of String)("Album"), .Annee = StrReverse(alb.Field(Of Integer)("Annee").ToString()) }