如何使用 LINQ Contains(string[]) 而不是 Contains(string)
Posted
技术标签:
【中文标题】如何使用 LINQ Contains(string[]) 而不是 Contains(string)【英文标题】:How do I use LINQ Contains(string[]) instead of Contains(string) 【发布时间】:2010-09-16 17:35:51 【问题描述】:我有一个大问题。
我得到了一个 linq 查询,简单来说就是这样:
from xx in table
where xx.uid.ToString().Contains(string[])
select xx
string[]
数组的值可以是 (1,45,20,10,etc...) 之类的数字
.Contains
的默认值为 .Contains(string)
。
我需要它来代替:.Contains(string[])
...
编辑:一位用户建议为string[]
编写一个扩展类。我想学习如何,但有人愿意为我指明正确的方向吗?
编辑: uid 也是一个数字。这就是它被转换为字符串的原因。
帮助任何人?
【问题讨论】:
您需要澄清 uid 可能看起来像什么,以及什么会被视为匹配项。 举个例子就好了。在我看来,问题是要求一个 UID,例如:CA1FAB689C33 和数组:“42”、“2259”、“CA” 相反更有意义:string[].Contains(xx.uid) 【参考方案1】:怎么样:
from xx in table
where stringarray.Contains(xx.uid.ToString())
select xx
【讨论】:
NotSupportedException: 类型'System.String[]'不支持比较运算符 谢谢但再试一次? +1,如果这确实是他们想要的。问题不是很清楚。【参考方案2】:这是一种编写扩展方法的示例(注意:我不会将它用于非常大的数组;另一种数据结构会更合适...):
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;
【讨论】:
等同于 public static bool Contains(this string[] stringarray, string pat) return Array.IndexOf(stringarray, pat) != -1; string[] 实现了 IEnumerable我相信你也可以这样做。
from xx in table
where (from yy in string[]
select yy).Contains(xx.uid.ToString())
select xx
【讨论】:
与“where stringArray.Contains(xx.uid.ToString())”相同,不需要在查询中环绕【参考方案4】:spoulson 几乎是正确的,但您需要先从string[]
创建一个List<string>
。实际上,如果 uid 也是 int
,List<int>
会更好。 List<T>
支持 Contains()
。执行uid.ToString().Contains(string[])
意味着作为字符串的 uid 包含作为子字符串的数组的所有值???即使您确实编写了扩展方法,它的感觉也是错误的。
[编辑]
除非像 Mitch Wheat 演示的那样更改它并为 string[]
编写它,否则您就可以跳过转换步骤。
[结束编辑]
如果您不执行扩展方法,这就是您想要的(除非您已经将潜在的 uid 集合作为整数 - 然后只需使用 List<int>()
代替)。这使用了我认为更简洁的链式方法语法,并且
转换为 int 以确保查询可以与更多提供程序一起使用。
var uids = arrayofuids.Select(id => int.Parse(id)).ToList();
var selected = table.Where(t => uids.Contains(t.uid));
【讨论】:
谢谢。这是正确的答案……再想一想?可以说 arrayuids 也是一个 linq 查询。有什么方法可以将两个语句都归结为数据库中的一个查询? 根据 MSDN,string[] 实现了 IEnumerableList<int>
,然后跳过 ToString
调用。【参考方案5】:
试试下面的。
string input = "someString";
string[] toSearchFor = GetSearchStrings();
var containsAll = toSearchFor.All(x => input.Contains(x));
【讨论】:
我真的希望人们在标记你时留下评论。特别是因为我提供的答案是 100% 正确的。 不是我,但 All() 不是简单地返回一个布尔值,指示所有项目在哪里符合条件吗?并将 toSearchFor 初始化为 null 保证 NullReferenceException。 我将 null 问题编辑为我想要输入的内容。是的。这有效地确保了 toSearchFor 中的所有字符串都包含在输入字符串中。 我根本不明白这是如何回答这个问题的。这个问题对你有影响吗?【参考方案6】:如果您真的想复制 包含,但对于数组,这里有一个 extension method 和示例代码供使用:
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;
【讨论】:
+1 @Jason,你应该把这个完全提交给ExtensionMethod.net 谢谢你的代码,它今天解决了我的问题! 我认为你的意思是 !string.IsNullOrEmpty(str) && values.Length > 0 你是对的。我改变了它,虽然它没有功能影响。我在工作中使用这样的功能。我必须检查一下! @JasonJackson 我意识到这是旧的(ish),但是(正如格雷格所提到的)你不想要一个“and also”而不是那个条件中的“or else”吗? @TiesonT。 "or else" 和 "and Also" 条件句最终都会得到函数返回的相同结果;如果!string.IsNullOrEmpty(str)
检查通过,导致values.Length > 0
条件被忽略,但Values的长度为0,那么它会转到foreach
然后立即中断,因为没有数组中的条目,直接转到return false
。【参考方案7】:
那么我是否正确地假设 uid 是唯一标识符 (Guid)?这只是可能场景的一个示例,还是您真的试图找到与字符串数组匹配的 guid?
如果这是真的,您可能需要重新考虑整个方法,这似乎是一个非常糟糕的主意。您可能应该尝试将 Guid 与 Guid 匹配
Guid id = new Guid(uid);
var query = from xx in table
where xx.uid == id
select xx;
老实说,我无法想象使用“包含”将字符串数组与 Guid 的内容进行匹配会是一个好主意。一方面, Contains() 不会保证 Guid 中的数字顺序,因此您可能会匹配多个项目。更不用说以这种方式比较 guid 会比直接进行比较慢。
【讨论】:
【参考方案8】:你应该反过来写,检查你的特权用户 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'关键字进行过滤。
【讨论】:
只要您的参数不超过 2100 个,此方法就可以正常工作。【参考方案9】:我设法找到了一个解决方案,但不是一个很好的解决方案,因为它需要使用 AsEnumerable() 来返回数据库中的所有结果,幸运的是我的表中只有 1k 条记录,所以它并不是很明显,但是这里有。
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;
我想要的是找到所有用户 他们的全名包含所有 “搜索”中的元素。我试过一个 多种不同的方式,所有这些 没有为我工作。
我也试过
var users = from u in ctx.Users select u; foreach (string s in search) users = users.Where(u => u.FullName.Contains(s));
这个版本只找到那些 包含搜索中的最后一个元素 数组。
【讨论】:
【参考方案10】:我找到的最佳解决方案是继续在 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 的强大功能......当然,您可以生成任何您想要的表值函数以获得相同的效果!
【讨论】:
【参考方案11】:我相信你真正想做的是: 让我们想象一个场景 你有两个数据库 他们有一张共同的产品表 并且您想从表“A”中选择 id 与“B”相同的产品
使用方法 contains 太复杂了,无法做到这一点 我们正在做的是一个交集,并且有一个方法叫做交集
来自 msdn 的示例: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1
int [] 数字 = (0, 2, 4, 5, 6, 8, 9); int [] numbersB = (1, 3, 5, 7, 8); var = commonNumbers numbersA.Intersect (numbersB);
我认为你需要的东西很容易通过交集来解决
【讨论】:
【参考方案12】:string[] stringArray = 1,45,20,10;
from xx in table
where stringArray.Contains(xx.uid.ToString())
select xx
【讨论】:
【参考方案13】:或者,如果您已经将数据放在列表中并且更喜欢其他 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();
【讨论】:
【参考方案14】:.NET 4.0 中的 LINQ 为您提供了另一种选择; .Any() 方法;
string[] values = new[] "1", "2", "3" ;
string data = "some string 1";
bool containsAny = values.Any(data.Contains);
【讨论】:
很好的答案,Any()
和 All()
方法的表达式非常简单 :) 我可以使用 t => words.All(w => t.Title.Contains(w))
。【参考方案15】:
from xx in table
where xx.uid.Split(',').Contains(string value )
select xx
【讨论】:
【参考方案16】:检查这个扩展方法:
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;
【讨论】:
【参考方案17】:这是一个迟到的答案,但我相信它仍然有用。 我创建了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);
或者执行一个RankedSearch
,它返回IQueryable<IRanked<T>>
,它只包含一个显示搜索词出现次数的属性:
//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
希望这对未来的访客有所帮助
【讨论】:
是的,它是专门针对实体框架构建的 我可以将它与 .Where() 方法一起使用吗? 是的,它适用于IQueryable
和 IEnumerable
- 请注意,如果将其链接到 IEnumerable,它将在内存中运行,而不是构建查询并将其发送到来源【参考方案18】:
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);
【讨论】:
【参考方案19】:试试:
var stringInput = "test";
var listOfNames = GetNames();
var result = from names in listOfNames where names.firstName.Trim().ToLower().Contains(stringInput.Trim().ToLower());
select names;
【讨论】:
虽然此代码可以回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将改善答案的长期价值。【参考方案20】: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())
【讨论】:
【参考方案21】: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;
【讨论】:
【参考方案22】: string texto = "CALCA 40";
string[] descpart = texto.Split(' ');
var lst = (from item in db.InvItemsMaster
where descpart.All(val => item.itm_desc.Contains(val))
select item
).ToList();
Console.WriteLine("ITM".PadRight(10) + "DESC".PadRight(50)+"EAN".PadRight(14));
foreach(var i in lst)
Console.Write(i.itm_id.ToString().PadRight(10));
Console.Write(i.itm_desc.ToString().PadRight(50));
Console.WriteLine(i.itm_ean.ToString().PadRight(14));
Console.ReadKey();
【讨论】:
我们,来到 SO。请不要给出“仅代码”的答案。您能否添加一些解释这是如何解决问题的,并且其他 21 个答案尚未涵盖?以上是关于如何使用 LINQ Contains(string[]) 而不是 Contains(string)的主要内容,如果未能解决你的问题,请参考以下文章
无法通过 Linq 方法 Contains() 针对 char 数组检查字符串,因为该数组不是 String 类型,转换为 String 类型失败