Comment utiliser LINQ Contains (string[]) au lieu de Contains (string)
j'ai une grande question.
j'ai obtenu une requête linq pour le mettre ressemble tout simplement à ceci:
from xx in table
where xx.uid.ToString().Contains(string[])
select xx
les valeurs du tableau string[]
seraient des nombres comme (1,45,20,10,etc...)
la valeur par défaut pour .Contains
est .Contains(string)
.
j'en ai besoin pour faire ceci à la place: .Contains(string[])
...
modifier: un utilisateur a suggéré d'écrire une classe d'extension pour string[]
. J'aimerais savoir comment, mais quelqu'un est-il prêt à m'indiquer la bonne direction?
EDIT : L'uid serait également un certain nombre. C'est pourquoi il est converti en chaîne de caractères.
aider quelqu'un?
20 réponses
spoulson a presque raison, mais vous devez créer un List<string>
de string[]
d'abord. En fait un List<int>
serait mieux si uid est aussi int
. List<T>
prend en charge Contains()
. Faire uid.ToString().Contains(string[])
impliquerait que l'uid comme chaîne contient toutes les valeurs du tableau comme substrat??? Même si vous n'écrivez la méthode d'extension le sens qu'elle serait une erreur.
[MODIFIER]
à moins que vous ne le changiez et que vous ne l'écriviez pour string[]
comme le démontre Mitch Wheat, alors vous pourriez sauter l'étape de conversion.
[ENDEDIT]
voici ce que vous voulez, si vous ne faites pas la méthode d'extension (à moins que vous ayez déjà la collection d'UID potentiels comme ints -- alors il suffit d'utiliser List<int>()
à la place). Cela utilise la syntaxe de la méthode enchaînée, qui je pense est plus propre, et
l' conversion en int pour s'assurer que la requête peut être utilisée avec plus de fournisseurs.
var uids = arrayofuids.Select(id => int.Parse(id)).ToList();
var selected = table.Where(t => uids.Contains(t.uid));
si vous cherchez vraiment à répliquer contient , mais pour un tableau, voici un méthode d'extension et un exemple de code d'utilisation:
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;
}
}
}
essayez ce qui suit.
string input = "someString";
string[] toSearchFor = GetSearchStrings();
var containsAll = toSearchFor.All(x => input.Contains(x));
LINQ in .NET 4.0 a une autre option pour vous; le .Toute méthode ();
string[] values = new[] { "1", "2", "3" };
string data = "some string 1";
bool containsAny = values.Any(data.Contains);
ou si vous avez déjà les données dans une liste et préférez l'autre format 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();
Que Diriez-vous de:
from xx in table
where stringarray.Contains(xx.uid.ToString())
select xx
ceci est un exemple d'une façon d'écrire une méthode d'extension (note: Je ne l'utiliserais pas pour de très grands tableaux; une autre structure de données serait plus appropriée...):
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;
}
}
}
C'est une réponse tardive, mais je crois qu'elle est encore utile .
J'ai créé le NinjaNye .SearchExtension paquet nuget qui peut aider à résoudre ce problème même.:
string[] terms = new[]{"search", "term", "collection"};
var result = context.Table.Search(terms, x => x.Name);
vous pouvez également rechercher des propriétés à chaînes multiples
var result = context.Table.Search(terms, x => x.Name, p.Description);
ou effectuer un RankedSearch
qui retourne IQueryable<IRanked<T>>
qui comprend simplement une propriété qui montre combien de fois les termes de recherche sont apparus:
//Perform search and rank results by the most hits
var result = context.Table.RankedSearch(terms, x => x.Name, x.Description)
.OrderByDescending(r = r.Hits);
Il ya un guide plus complet sur les projets GitHub page: https://github.com/ninjanye/SearchExtensions
Espérons que cela aide les visiteurs à venir
je crois que vous pourriez aussi faire quelque chose comme cela.
from xx in table
where (from yy in string[]
select yy).Contains(xx.uid.ToString())
select xx
Linq méthode d'extension. Fonctionnera avec n'importe quel objet IEnumerable:
public static bool ContainsAny<T>(this IEnumerable<T> Collection, IEnumerable<T> Values)
{
return Collection.Any(x=> Values.Contains(x));
}
Utilisation:
string[] Array1 = {"1", "2"};
string[] Array2 = {"2", "4"};
bool Array2ItemsInArray1 = List1.ContainsAny(List2);
est-ce que je suppose correctement que uid est un identifiant Unique (Guid)? Est-ce juste un exemple d'un scénario possible ou essayez-vous vraiment de trouver un guid qui correspond à un tableau de cordes?
Si cela est vrai, vous pouvez vraiment repenser toute cette approche, cela semble être une très mauvaise idée. Vous devriez probablement essayer de faire correspondre un Guid à un Guid
Guid id = new Guid(uid);
var query = from xx in table
where xx.uid == id
select xx;
honnêtement, je ne peux pas imaginer un scénario où l'appariement d'un réseau de cordes utiliser "contains" au contenu d'un guide serait une bonne idée. Pour une chose, Contains () ne garantira pas l'ordre des nombres dans le Guid de sorte que vous pouvez potentiellement faire correspondre plusieurs éléments. Sans parler de comparer les guids de cette façon serait beaucoup plus lent que juste le faire directement.
vous devriez l'écrire dans l'autre sens, en vérifiant votre liste d'ID utilisateur privilégié contient l'id sur cette rangée de la table:
string[] search = new string[] { "2", "3" };
var result = from x in xx where search.Contains(x.uid.ToString()) select x;
LINQ se comporte ici très lumineux et le convertit en un bon énoncé 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'
qui incorpore basicly le contenu du tableau 'search' dans la requête sql, et fait le filtrage avec le mot-clé 'IN' dans SQL.
j'ai réussi à trouver une solution, mais pas une grande car elle nécessite l'utilisation AsEnumerable() qui va retourner tous les résultats de la DB, heureusement que je n'ai que 1K enregistrements dans la table de sorte qu'il n'est pas vraiment perceptible, mais voilà.
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;
Mon post original suit:
Comment faites-vous l'inverse? Je veux faire quelque chose comme ce qui suit dans entité 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;
ce que je veux est de trouver tous les utilisateurs où leur Nom complet contient tous les éléments de la "recherche". J'ai essayé un certain nombre de façons différentes, qui toutes n'ont pas été de travailler pour moi.
j'ai aussi essayé
var users = from u in ctx.Users select u; foreach (string s in search) { users = users.Where(u => u.FullName.Contains(s)); }
cette version ne trouve que ceux qui contenir le dernier élément de la recherche tableau.
la meilleure solution que j'ai trouvé était d'aller de L'avant et de créer une fonction de valeur de Table en SQL qui produit les résultats, tels que:
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')
ensuite, vous faites simplement glisser la fonction dans votre LINQ.dbml designer et appelez-le comme vous faites vos autres objets. Le LINQ connaît même les colonnes de votre fonction stockée. Je l'appelle comme ceci ::
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
incroyablement simple et utilise vraiment la puissance de SQL et LINQ dans le application...et vous pouvez, bien sûr, générer une fonction à valeur de table que vous voulez pour les mêmes effets!
je crois que ce que vous voulez vraiment, c'est: imaginons un scénario vous avez deux bases de données et ils ont une table de produits en commun Et vous voulez sélectionner des produits du tableau "A" que id a en commun avec le" B "
l'utilisation de la méthode contains serait trop compliquée pour le faire ce que nous faisons est une intersection, et il y a une méthode appelée intersection pour cela
exemple de msdn: http://msdn.microsoft.com/en-us/vcsharp/aa336761.aspx#intersect1
int [] nombres = (0, 2, 4, 5, 6, 8, 9); int [] numbersB = (1, 3, 5, 7, 8); var = commonNumbers numbersA.Intersect (numbersB);
je pense que ce que vous avez besoin est facilement résolu avec l'intersection
vérifier cette méthode d'extension:
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
, Essayez:
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())
}