Come utilizzare LINQ Contains (stringa ) anziché Contains (stringa)

Ho una grande domanda.

Ho ottenuto una query su linq per metterla semplicemente così:

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

I valori dell’array string[] sarebbero numeri come (1,45,20,10, ecc …)

il valore predefinito per .Contains è .Contains(string) .

Ho bisogno di farlo invece: .Contains(string[])

EDIT: un utente ha suggerito di scrivere una class di estensione per string[] . Mi piacerebbe sapere come, ma chiunque sia disposto a indicarmi la giusta direzione?

EDIT: L’UID sarebbe anche un numero. Ecco perché è convertito in una stringa.

Aiuta qualcuno?

spoulson ha quasi ragione, ma è necessario prima creare una List dalla string[] . In realtà una List sarebbe meglio se anche uid fosse int . List supporta Contains() . Fare uid.ToString().Contains(string[]) implicherebbe che l’uid come una stringa contenga tutti i valori dell’array come una sottostringa ??? Anche se hai scritto il metodo di estensione, il senso di ciò sarebbe sbagliato.

[MODIFICARE]

A meno che tu non l’abbia cambiato in giro e lo abbia scritto per string[] come dimostra Mitch Wheat, allora sarai in grado di saltare il passaggio di conversione.

[EndEdit]

Ecco cosa vuoi, se non fai il metodo di estensione (a meno che tu non abbia già la raccolta di potenziali uid come ints), usa solo List() invece). Questo utilizza la syntax del metodo concatenato, che credo sia più pulito, e fa la conversione in int per garantire che la query possa essere utilizzata con più provider.

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

Se stai veramente cercando di replicare Contiene , ma per un array, ecco un metodo di estensione e un codice di esempio per l’utilizzo:

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

Prova quanto segue.

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

LINQ in .NET 4.0 ha un’altra opzione per te; il metodo .Any ();

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

O se hai già i dati in una lista e preferisci l’altro formato Linq 🙂

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

Che ne dite di:

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

Questo è un esempio di un modo di scrivere un metodo di estensione (nota: non lo userei per array molto grandi, un’altra struttura di dati sarebbe più appropriata …):

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

Questa è una risposta tardiva, ma credo che sia ancora utile .
Ho creato il pacchetto nuget NinjaNye.SearchExtension che può aiutare a risolvere questo problema:

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

È anche ansible cercare più proprietà di stringa

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

Oppure esegui una ricerca RankedSearch che restituisce IQueryable> che include semplicemente una proprietà che mostra quante volte sono apparsi i termini di ricerca:

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

C’è una guida più ampia sulla pagina GitHub dei progetti: https://github.com/ninjanye/SearchExtensions

Spero che questo aiuti i futuri visitatori

Credo che potresti anche fare qualcosa del genere.

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

Metodo di estensione Linq. Funzionerà con qualsiasi 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); 

Quindi sto assumendo correttamente che uid è un identificatore unico (Guid)? È solo un esempio di uno scenario ansible o stai davvero cercando di trovare un guid che corrisponda a una serie di stringhe?

Se questo è vero, potresti voler ripensare davvero a tutto questo approccio, questa sembra una pessima idea. Probabilmente dovresti cercare di abbinare un Guid a un Guid

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

Onestamente non riesco a immaginare uno scenario in cui la corrispondenza con un array di stringhe che utilizza “contiene” i contenuti di una guida sarebbe una buona idea. Per prima cosa, Contains () non garantisce l’ordine dei numeri nella Guida in modo da poter potenzialmente abbinare più elementi. Per non parlare del confronto tra i guids in questo modo sarebbe molto più lento di farlo direttamente.

Dovresti scriverlo al contrario, controllando la tua lista di ID utente priviligato che contiene l’id su quella riga di tabella:

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

LINQ si comporta abbastanza bene qui e lo converte in una buona istruzione 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' 

che in sostanza incorpora il contenuto dell’array ‘search’ nella query sql e fa il filtraggio con la parola chiave ‘IN’ in SQL.

Sono riuscito a trovare una soluzione, ma non eccezionale visto che richiede l’utilizzo di AsEnumerable () che restituirà tutti i risultati dal DB, fortunatamente ho solo 1k record nella tabella, quindi non è davvero notevole, ma qui va .

 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; 

Il mio post originale segue:

Come fai il contrario? Voglio fare qualcosa di simile al seguente nel framework di 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; 

Quello che voglio è trovare tutti gli utenti in cui il loro FullName contiene tutti gli elementi in `ricerca ‘. Ho provato un certo numero di modi diversi, che non hanno funzionato per me.

Ho anche provato

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

Questa versione trova solo quelli che contengono l’ultimo elemento nell’array di ricerca.

La soluzione migliore che ho trovato è stata quella di andare avanti e creare una funzione con valori di tabella in SQL che produca i risultati, come ad esempio:

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

Quindi, trascina semplicemente la funzione nel tuo designer LINQ.dbml e chiamala come fai con gli altri tuoi oggetti. LINQ conosce persino le colonne della funzione memorizzata. Lo chiamo così ::

 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

Incredibilmente semplice e davvero sfrutta la potenza di SQL e LINQ nell’applicazione … e puoi, naturalmente, generare qualsiasi funzione di valore di tabella che desideri per gli stessi effetti!

Credo che quello che vuoi veramente sia: immaginiamo uno scenario con due database e hanno una tabella di prodotti in comune E vuoi selezionare i prodotti dalla tabella “A” che ID ha in comune con la “B”

usare il metodo contiene sarebbe troppo complicato per fare ciò che stiamo facendo è un incrocio, e c’è un metodo chiamato intersezione per quello

un esempio di 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);

Penso che ciò di cui hai bisogno sia facilmente risolto con l’intersezione

Controlla questo metodo di estensione:

 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 

Provare:

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