103 votes

Comment utiliser LINQ Contains(string[]) au lieu de Contains(string) ?

J'ai une grande question.

J'ai une requête linq qui, pour faire simple, ressemble à ceci :

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

Les valeurs des string[] le tableau serait constitué de nombres comme (1,45,20,10,etc...)

la valeur par défaut pour .Contains est .Contains(string) .

J'ai besoin qu'il fasse ça à la place : .Contains(string[]) ...

EDIT : Un utilisateur a suggéré d'écrire une classe d'extension pour string[] . J'aimerais apprendre à le faire, mais quelqu'un peut-il m'indiquer la voie à suivre ?

EDIT : L'uid serait également un nombre. C'est pourquoi il est converti en chaîne de caractères.

Quelqu'un peut aider ?

0 votes

Vous devez préciser à quoi pourrait ressembler un uid, et ce qui serait considéré comme une correspondance.

3 votes

Un exemple serait le bienvenu. Il me semble que la question demande un UID comme : CA1FAB689C33 et le tableau comme : { "42", "2259", "CA" }

3 votes

L'inverse est plus logique : string[].Contains( xx.uid )

89voto

tvanfosson Points 268301

Spoulson a presque raison, mais vous devez créer une List<string> de string[] première. En fait, un List<int> Ce serait mieux si l'uid était aussi int . List<T> soutient Contains() . Faire uid.ToString().Contains(string[]) impliquerait que l'uid en tant que chaîne de caractères contient toutes les valeurs du tableau en tant que sous-chaîne ??? Même si vous avez écrit la méthode d'extension, le sens de celle-ci serait erroné.

[EDIT]

A moins que vous ne l'ayez modifié et écrit pour string[] comme le démontre Mitch Wheat, alors vous pourriez simplement sauter l'étape de la conversion.

[ENDEDIT]

Voici ce que vous voulez, si vous ne faites pas la méthode d'extension (à moins que vous n'ayez déjà la collection d'uids potentiels sous forme d'ints -- alors utilisez simplement List<int>() à la place). Cette méthode utilise la syntaxe des méthodes enchaînées, qui me semble plus propre, et fait la 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));

0 votes

Merci. C'était la bonne réponse... Une autre idée ? Disons que les arrayuids sont aussi une requête linq. Y a-t-il un moyen de ramener les deux déclarations à une seule requête de la base de données ?

4 votes

Selon MSDN, string[] implémente IEnumerable<T>, qui possède une méthode Contains. Par conséquent, il n'est pas nécessaire de convertir le tableau en une IList<T>. msdn.microsoft.com/fr/us/library/19e6zeyy.aspx

0 votes

Le dernier .ToString() provoque des erreurs dans mon cas. Plus précisément, LINQ to Entities ne reconnaît pas la méthode 'System.String ToString()', et cette méthode ne peut pas être traduite dans une expression de magasin..... Après l'avoir supprimé, le lambda a fonctionné pour moi.

40voto

Jason Jackson Points 11563

Si vous cherchez vraiment à reproduire Contient mais pour un tableau, voici un méthode d'extension et un exemple de code pour l'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;
        }
    }
}

2 votes

+1 @Jason, tu devrais carrément soumettre ceci à ExtensionMethod.net Merci pour ce super code, il a résolu mon problème aujourd'hui !

4 votes

Je pense que vous vouliez dire !string.IsNullOrEmpty(str) && values.Length > 0

0 votes

Vous avez raison. Je l'ai modifié, même si cela n'a pas d'impact fonctionnel. J'utilise une fonction comme celle-ci au travail. Je vais devoir la vérifier !

23voto

JaredPar Points 333733

Essayez ce qui suit.

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

2 votes

J'aimerais vraiment que les gens laissent un commentaire quand ils vous notent. Surtout que la réponse que j'ai donnée est 100% correcte.

0 votes

Ce n'était pas moi, mais All() ne renvoie-t-il pas simplement un bool indiquant où tous les éléments correspondent à la condition ? Et initialiser toSearchFor à null garantit une NullReferenceException.

0 votes

J'ai modifié la question de la nullité pour qu'elle soit ce que j'avais l'intention de taper. Oui sur Tout. Cela garantit effectivement que toutes les chaînes de toSearchFor sont contenues dans la chaîne d'entrée.

8voto

JumpingJezza Points 2608

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

3voto

spoulson Points 13391

Pourquoi pas :

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

0 votes

NotSupportedException : Les opérateurs de comparaison ne sont pas pris en charge pour le type 'System.String[]' Merci, mais essayez à nouveau ?

0 votes

+1, si c'est vraiment ce qu'ils veulent. Ce n'est pas très clair dans la question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X