¿Existe un operador C # IN?

91

En SQL, puede utilizar la siguiente sintaxis:

SELECT *
FROM MY_TABLE
WHERE VALUE_1 IN (1, 2, 3)

¿Existe un equivalente en C #? El IDE parece reconocer "in" como palabra clave, pero no parece que pueda encontrar ninguna información sobre él.

Entonces, ¿es posible hacer algo como lo siguiente:

int myValue = 1;
if (myValue in (1, 2, 3))
    // Do something

En vez de

int myValue = 1;
if (myValue == 1 || myValue == 2 || myValue == 3)
    // Do something
Paul Michaels
fuente
He editado esto un poco para aclarar lo que estaba tratando de comparar
Paul Michaels
verifique otra respuesta agregada por mí
Pranay Rana
Esto ya se ha preguntado varias veces en stackoverflow ...
chiccodoro
3
@chiccodoro si esta pregunta se ha hecho antes, márquela como un duplicado y publique una respuesta con el enlace a la pregunta original, no deje un comentario negativo
Hannish

Respuestas:

128

Si quisiera escribir .In, entonces podría crear una extensión que le permita hacerlo.

static class Extensions
{

    public static bool In<T>(this T item, params T[] items)
    {
        if (items == null)
            throw new ArgumentNullException("items");

        return items.Contains(item);
    }

}


class Program
{

    static void Main()
    {


        int myValue = 1;

        if (myValue.In(1, 2, 3))
            // Do Somthing...

        string ds = "Bob";

        if (ds.In("andy", "joel", "matt")) 
        // Do Someting...
    }
}
Andy Robinson
fuente
1
Solo recuerde agregar usando System.Linq;
Tanner Ornelas
Es mucho mejor leer que contiene ... Más fácil de entender
Konrad
85

List.Contains()creo que lo que estás buscando. C # tienein keyword y no tiene un operatorpropósito completamente diferente al que se refiere en SQL.

Hay dos formas de usar inpalabras clave en C #. Suponga que tiene una cadena [] o Lista en C #.

        string[] names; //assume there are some names;

        //find all names that start with "a"
        var results = from str in names
                      where str.StartsWith("a")
                      select str;

        //iterate through all names in results and print
        foreach (string name in results)
        {
            Console.WriteLine(name);
        }

Refiriendo su edición, pondría su código de esta manera para hacer lo que necesita.

        int myValue = 1;
        List<int> checkValues = new List<int> { 1, 2, 3 };

        if (checkValues.Contains(myValue))
            // Do something 
esta. __curious_geek
fuente
4
La gente ve SQL y salta instantáneamente a LINQ, pero esta función simple es probablemente exactamente lo que él quiere
Bart van Heukelom
30

Puedes hacerlo:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}
JwJosefy
fuente
2
Preferí esta respuesta a las más votadas, ya que el objetivo de querer hacer IN en lugar de verificaciones de igualdad repetidas es reducir la complejidad del código, ¡y esto es agradable, corto y simple!
MrVimes
7

Suele utilizar el Containsmétodo de una colección.

myCollection.Where(p => Enumerable.Range(1,3).Contains(p));

Espero que ayude.

suerte
fuente
6

No hay un operador "in" en C #, la palabra clave "in" se usa solo con "foreach (... in ...)" o "from ... in ...".

El equivalente LINQ de su consulta SQL sería:

List<int> list = new List<int> { 1, 2, 3 };
var query = from row in my_table
            where list.Contains(row.value1)
            select row;
Daniel
fuente
4

Duplicado de: LINQ to SQL en y no en

select * from table where fieldname in ('val1', 'val2') 

o

select * from table where fieldname not in (1, 2) 

El equivalente de consultas IN y NOT IN en LINQ to SQL sería algo como esto:

List<string> validValues = new List<string>() { "val1", "val2"}; 
var qry = from item in dataContext.TableName 
          where validValues.Contains(item.FieldName) 
          select item; 

y esto:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 
Pranay Rana
fuente
Sí, lo siento, he editado mi pregunta, ya que lo que estoy preguntando no se relaciona con linq
Paul Michaels
4

Estoy de acuerdo en que la mejor manera de implementar el operador In es con un método de extensión. Lo hice un poco diferente:

public static bool In(this string str, string CommaDelimintedStringSet)
{
    string[] Values = CommaDelimintedStringSet.Split(new char[] { ',' });
    foreach (string V in Values)
    {
       if (str == V)
         return true;
    }
    return false;
}

La diferencia es que no tiene que poner comillas alrededor de cada valor, solo el conjunto completo de valores delimitados por comas, que es más fácil de escribir:

bool result = MyString.In("Val1,Val2,Val3");
Chuck Bevitt
fuente
Sería mejor utilizar param-arrays con esta función. Me gusta public static bool In(this string str, params string[] stringSet)y llámalo comobool result = myString.In("Val1", "Val2", "Val3")
Manuel Hoffmann
2

Puede escribir una extensión. Escribí hace una vez, para hacer código como

if(someObject.stringPropertyX.Equals("abc") || someObject.stringPropertyX.Equals("def") || ....){
    //do something
    ...
}else{
   //do something other...
   ....
}

más legible con una extensión en la que uno podía escribir

if(someObject.stringPropertyX.In("abc", "def",...,"xyz"){
   //do something
   ...
}else{
  //do something other...
  ....
}

Aquí está el código :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Some.Namespace.Extenders
{
    public static class StringExtender
    {
        /// <summary>
        /// Evaluates whether the String is contained in AT LEAST one of the passed values (i.e. similar to the "in" SQL clause)
        /// </summary>
        /// <param name="thisString"></param>
        /// <param name="values">list of strings used for comparison</param>
        /// <returns><c>true</c> if the string is contained in AT LEAST one of the passed values</returns>
        public static bool In(this String thisString, params string[] values)
        {
            foreach (string val in values)
            {
                if (thisString.Equals(val, StringComparison.InvariantCultureIgnoreCase))
                    return true;
            }

            return false; //no occurence found
        }
    }
}

Este es el específico para mis necesidades en ese momento, pero puede adaptarlo y modificarlo para que coincida con más tipos diferentes.

Juri
fuente
2

Para dígitos del 0 al 9:

"123".Contains(myValue)

Para cualquier otra cosa:

"|1|2|3|".Contains("|" + myValue + "|")
usuario3354025
fuente
2

Para su pregunta actualizada, también puede usar una declaración de cambio.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}
Pranay Rana
fuente
1
Esto es lo que terminé haciendo. Supongo que el consenso es que realmente no hay ninguna facilidad para esto en C #.
Paul Michaels
5
Realmente no habría aceptado esto, porque NO es una respuesta a la pregunta del operador "in". En su lugar, vea la respuesta más votada ...
chiccodoro
6
¡No recomendaría este enfoque en absoluto! No es escalable y tiene la capacidad de hacer miserable la vida de sus compañeros programadores.
deciclón
3
@decyclone: ​​Sí, se trata de mantenibilidad. codifique como si el próximo programador que lo reemplace fuera un asesino en serie y supiera dónde vive.
esto. __curious_geek
No estoy de acuerdo, no hubo una respuesta real a la pregunta (o la respuesta fue "no, eso no existe en C #"), por lo que esta me pareció la alternativa más cercana. También hay que tener en cuenta que la pregunta se basó en la funcionalidad del lenguaje y no en el estilo.
Paul Michaels
1

No hay un operador in que busque un valor en una colección, sino que es un método de la colección, llamado Contains.

La solución más escalable es utilizar a HashSetcomo colección. Comprobando un valor en unHashSet está cerca de una operación O (1), en comparación con hacerlo en a Listdonde es una operación O (n). Eso significa que puede empaquetar muchos valores en a HashSety aún así es rápido, mientras busca un valor en unList vuelve más lento cuanto más valores tiene.

Ejemplo:

var set = new HashSet<int>();
set.Add(1);
set.Add(2);
set.Add(3);

var result = items.Select(i => set.Contains(i.value));
Guffa
fuente
1

Común, LINQ mucho más potente:

var list = new List<string> { "Tomato", "Orange", "Mango"};
var query = from i in my_table
            from v in list
            where i.Name.StartsWith(v)
            select i;
bjolfr
fuente
0

La inpalabra clave en C # es para la foreachdeclaración y para las expresiones de consulta LINQ. No existe una funcionalidad equivalente al inoperador de SQL en C # per se, pero LINQ ofrece una funcionalidad similar con Contains().

var list = {1, 2, 3}
var filtered = (
    from item in items
    where list.Contains(item)
    select item).ToArray().
Papi
fuente
0

Hago algo como esto:

var shippingAddress = checkoutContext.Addresses.Where(a => (new HashSet<AddressType> { AddressType.SHIPPING_ONLY, AddressType.BILLING_AND_SHIPPING }).Contains(a.AddressType) && a.Id == long.Parse(orderDto.ShippingAddressId)).FirstOrDefault();
BRBdot
fuente