Есть ли оператор C # IN?

91

В SQL вы можете использовать следующий синтаксис:

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

Есть ли эквивалент в C #? Кажется, что IDE распознает "in" как ключевое слово, но я не могу найти по нему никакой информации.

Итак, можно ли сделать что-то вроде следующего:

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

Вместо того

int myValue = 1;
if (myValue == 1 || myValue == 2 || myValue == 3)
    // Do something
Пол Майклс
источник
Я немного отредактировал это, чтобы прояснить то, что я пытался сравнить
Пол Майклс
проверьте еще один ответ, добавленный мной
Pranay Rana
Об этом уже несколько раз спрашивали в stackoverflow ...
chiccodoro 02
3
@chiccodoro, если этот вопрос был задан раньше, пометьте его как дубликат и опубликуйте ответ со ссылкой на исходный вопрос, а не просто оставляйте отрицательный комментарий
Ханниш

Ответы:

128

Если вы хотите написать .In, вы можете создать расширение, которое позволит вам это сделать.

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...
    }
}
Энди Робинсон
источник
1
Просто не забудьте добавить using System.Linq;
Таннер Орнелас
«В» гораздо лучше читать, чем содержать… Легче понять
Конрад
85

List.Contains()я думаю то, что вы ищете. C # имеет, in keywordа не тот, operatorкоторый служит совершенно другой цели, чем то, о чем вы говорите в SQL.

Есть два способа использования inключевого слова в C #. Предположим, у вас есть строка [] или список в 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);
        }

Ссылаясь на ваше редактирование, я бы поместил ваш код таким образом, чтобы делать то, что вам нужно.

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

        if (checkValues.Contains(myValue))
            // Do something 
этот. __curious_geek
источник
4
Люди видят SQL и мгновенно переходят к LINQ, но эта простая функция, вероятно, именно то, что ему
нужно,
30

Ты можешь это сделать:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}
JwJosefy
источник
2
Я предпочел этот ответ тем, за которые проголосовали более высокие, поскольку весь смысл желания делать IN вместо повторных проверок равенства состоит в том, чтобы уменьшить сложность кода, и это красиво, коротко и просто!
MrVimes 01
7

Обычно вы используете Containsметод коллекции.

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

Я надеюсь, что это помогает.

удачливый
источник
6

В C # нет оператора «in», ключевое слово «in» используется только с «foreach (... in ...)» или «from ... in ...».

Эквивалент LINQ вашего SQL-запроса:

List<int> list = new List<int> { 1, 2, 3 };
var query = from row in my_table
            where list.Contains(row.value1)
            select row;
Даниэль
источник
4

Дубликат: LINQ to SQL в, а не в

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

или

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

Эквивалент запросов IN и NOT IN в LINQ to SQL будет примерно таким:

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

и это:

List<int> validValues = new List<int>() { 1, 2}; 
var qry = from item in dataContext.TableName 
          where !validValues.Contains(item.FieldName) 
          select item; 
Праная Рана
источник
Да - извините, я отредактировал свой вопрос, так как то, что я спрашиваю, не имеет отношения к linq
Пол Майклс
4

Я согласен, что лучший способ реализовать оператор In - использовать метод расширения. Я сделал немного иначе:

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

Разница в том, что вам не нужно заключать в кавычки каждое значение, а только весь набор значений, разделенных запятыми, которые легче набрать:

bool result = MyString.In("Val1,Val2,Val3");
Чак Бевитт
источник
Было бы лучше использовать массивы параметров с этой функцией. Как public static bool In(this string str, params string[] stringSet)и назовите это какbool result = myString.In("Val1", "Val2", "Val3")
Мануэль Хоффманн
2

Вы можете написать расширение. Я писал однажды назад, чтобы сделать код вроде

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

более читаемый с расширением, что можно было написать

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

Вот код :

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

Это тот, который специфичен для моих нужд в то время, но вы можете адаптировать и модифицировать его для соответствия большему количеству разных типов.

Юри
источник
2

Для цифр от 0 до 9:

"123".Contains(myValue)

Для любых других вещей:

"|1|2|3|".Contains("|" + myValue + "|")
user3354025
источник
2

Для вашего обновленного вопроса вы также можете использовать оператор-переключатель.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}
Праная Рана
источник
1
Вот что я в итоге сделал. Я полагаю, что все согласны с тем, что в C # на самом деле нет возможности для этого.
Paul Michaels
5
Я бы на самом деле не принял это, потому что это НЕ ответ на вопрос оператора in. Вместо этого см.
Наиболее
6
Я бы вообще не рекомендовал такой подход! Он не масштабируется и может сделать жизнь ваших коллег-программистов невыносимой!
decyclone 02
3
@decyclone: ​​Да, все дело в ремонтопригодности. кодируйте так, как будто следующий программист, который придет на замену, будет серийным убийцей и знает, где вы живете.
это. __curious_geek 02
Я не согласен, фактического ответа на вопрос не было (или ответ был «нет, этого не существует в C #») - так что это казалось мне наиболее близкой альтернативой. Вы также должны иметь в виду, что вопрос был основан на функциональности языка, а не на стиле.
Пол Майклс
1

Нет оператора in, который ищет значение в коллекции, вместо этого это вызываемый метод коллекции Contains.

Наиболее масштабируемое решение - использовать в HashSetкачестве коллекции. Проверка значения в a HashSetблизка к операции O (1) по сравнению с выполнением этого в a, Listгде это операция O (n). Это означает, что вы можете упаковать много значений в a, HashSetи это по-прежнему быстро, а поиск значения в a Listбудет тем медленнее, чем больше у вас значений.

Пример:

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

var result = items.Select(i => set.Contains(i.value));
Гуффа
источник
1

Обычный, LINQ более мощный:

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
источник
0

inКлючевое слово в C # является для foreachзаявления и выражений запросов LINQ. Функциональности, эквивалентной оператору SQL inв C # как таковой, нет, но LINQ предлагает аналогичные функции с Contains().

var list = {1, 2, 3}
var filtered = (
    from item in items
    where list.Contains(item)
    select item).ToArray().
P Папа
источник
0

Я делаю примерно так:

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
источник