Como eu uso o LINQ Contains (string ) em vez de Contains (string)

Eu tenho uma grande pergunta.

Eu tenho uma consulta de linq para colocá-lo simplesmente se parece com isso:

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

Os valores da matriz string[] seriam números como (1,45,20,10, etc …)

o padrão para .Contains é .Contains(string) .

Eu preciso disso para fazer isso em vez disso: .Contains(string[])

EDIT: Um usuário sugeriu escrever uma class de extensão para string[] . Eu gostaria de aprender como, mas alguém disposto a me apontar na direção certa?

EDIT: O uid também seria um número. É por isso que é convertido em uma string.

Ajudar alguém?

spoulson está quase certo, mas você precisa criar uma List de string[] primeiro. Na verdade, uma List seria melhor se uid também fosse int . List suporta Contains() . Fazendo uid.ToString().Contains(string[]) implicaria que o uid como uma string contém todos os valores da matriz como uma substring ??? Mesmo se você escrever o método de extensão, o sentido seria errado.

[EDITAR]

A menos que você o tenha alterado e o tenha escrito como string[] como demonstra o Mitch Wheat, você poderá pular a etapa de conversão.

[ENDEDIT]

Aqui está o que você quer, se você não fizer o método de extensão (a menos que você já tenha a coleção de possíveis uids como ints – então apenas use List() ). Isso usa a syntax do método encadeado, que acho mais limpa, e faz a conversão para int para garantir que a consulta possa ser usada com mais provedores.

 var uids = arrayofuids.Select(id => int.Parse(id)).ToList(); var selected = table.Where(t => uids.Contains(t.uid)); 

Se você estiver realmente procurando replicar Contains , mas para um array, aqui está um método de extensão e código de exemplo para uso:

 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; } } } 

Experimente o seguinte.

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

LINQ no .NET 4.0 tem outra opção para você; o método .Any ();

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

Ou se você já tem os dados em uma lista e prefere o outro formato Linq 🙂

 List uids = new List(){"1", "45", "20", "10"}; List table = GetDataFromSomewhere(); List newTable = table.Where(xx => uids.Contains(xx.uid)).ToList(); 

E se:

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

Este é um exemplo de uma maneira de escrever um método de extensão (nota: eu não usaria isso para matrizes muito grandes; outra estrutura de dados seria mais apropriada …):

 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; } } } 

Esta é uma resposta tardia, mas acredito que ainda seja útil .
Eu criei o pacote nuget NinjaNye.SearchExtension que pode ajudar a resolver este problema:

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

Você também pode pesquisar várias propriedades de string

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

Ou execute um RankedSearch que retorne IQueryable> que simplesmente inclua uma propriedade que mostre quantas vezes os termos da pesquisa apareceram:

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

Existe um guia mais extenso na página de projetos do GitHub: https://github.com/ninjanye/SearchExtensions

Espero que isso ajude os futuros visitantes

Eu acredito que você também poderia fazer algo assim.

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

Método de extensão Linq. Funcionará com qualquer object IEnumerable:

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

Uso:

 string[] Array1 = {"1", "2"}; string[] Array2 = {"2", "4"}; bool Array2ItemsInArray1 = List1.ContainsAny(List2); 

Então, estou assumindo corretamente que uid é um Identificador Único (Guid)? Isso é apenas um exemplo de um cenário possível ou você está realmente tentando encontrar um guia que corresponda a um array de strings?

Se isso for verdade, você pode querer realmente repensar toda essa abordagem, isso parece uma péssima idéia. Você provavelmente deveria estar tentando combinar um Guid com um Guid

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

Eu honestamente não consigo imaginar um cenário em que a correspondência de um array de strings usando “contém” ao conteúdo de um Guid seja uma boa ideia. Por um lado, Contains () não garantirá a ordem dos números no Guid, então você pode potencialmente combinar vários itens. Sem mencionar que comparar guias dessa maneira seria muito mais lento do que apenas fazer isso diretamente.

Você deve escrevê-lo ao contrário, verificando se sua lista de ID de usuário privilegiado contém o ID nessa linha da tabela:

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

O LINQ se comporta bem claro aqui e o converte em uma boa instrução 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' 

que embute basicamente o conteúdo da matriz ‘search’ na consulta sql e faz a filtragem com a palavra-chave ‘IN’ no SQL.

Eu consegui encontrar uma solução, mas não uma grande, pois requer o uso de AsEnumerable (), que vai retornar todos os resultados do database, felizmente eu só tenho 1k registros na tabela por isso não é realmente perceptível, mas aqui vai .

 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; 

Meu post original segue:

Como você faz o contrário? Eu quero fazer algo como o seguinte na estrutura de entidade.

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

O que eu quero é encontrar todos os usuários onde seu FullName contém todos os elementos em `search ‘. Eu tentei várias maneiras diferentes, as quais não têm funcionado para mim.

Eu também tentei

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

Esta versão encontra apenas aqueles que contêm o último elemento na matriz de pesquisa.

A melhor solução que encontrei foi ir em frente e criar uma function com valor de tabela no SQL que produz os resultados, como ::

 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') 

Em seguida, basta arrastar a function para o designer LINQ.dbml e chamá-la como você faz com seus outros objects. O LINQ até conhece as colunas da sua function armazenada. Eu chamo assim:

 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 & "
", .NavigateUrl = "?ID=" & ee.ID} pnl_results.Controls.Add(hlink) Next

Incrivelmente simples e realmente utiliza o poder do SQL e do LINQ no aplicativo … e você pode, é claro, gerar qualquer function com valor de tabela que você deseja para os mesmos efeitos!

Eu acredito que o que você realmente quer fazer é: vamos imaginar um cenário você tem dois bancos de dados e eles têm uma tabela de produtos em comum E você quer selecionar produtos da tabela “A” que id tem em comum com o “B”

usando o método contém seria muito complicado para fazer isso o que estamos fazendo é uma interseção, e há um método chamado interseção para que

um exemplo de msdn: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1

int [] números = (0, 2, 4, 5, 6, 8, 9); int [] númerosB = (1, 3, 5, 7, 8); var = commonNumbers numbersA.Intersect (numbersB);

Eu acho que o que você precisa é facilmente resolvido com interseção

Verifique este método de extensão:

 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 { ///  /// Replicates Contains but for an array ///  /// The string. /// The values. ///  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 

Experimentar:

 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()) }