Чи існує оператор C # IN?


90

У 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

3
@chiccodoro, якщо це запитання було задано раніше, то позначте його як копію та опублікуйте відповідь із посиланням на оригінальне запитання, не просто залишайте негативний коментар
Ганніш

Відповіді:


127

Якщо ви хотіли писати .Тоді ви могли б створити розширення, яке дозволяє вам це робити.

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
Просто не забудьте додати за допомогою System.Linq;
Таннер Орнелас

В набагато краще читати, ніж містити ... Легше зрозуміти
Конрад

84

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 

4
Люди бачать SQL і миттєво переходять до LINQ, але ця проста функція, мабуть, саме те, що він хоче
Барт ван Хейкелом

30

Ви можете зробити це:

var x = 99; // searched value

if (new[] {1,2,3,99}.Contains(x))
{
   // do something
}

2
Я віддав перевагу цій відповіді більш голосованим, оскільки вся суть бажання робити IN замість повторних перевірок рівності полягає у зменшенні складності коду, і це приємно, коротко і просто!
MrVimes

1
Дякую @MrVimes!
JwJosefy

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 in and not in

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

або

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

Еквівалент запитів IN та NOT IN у LINQ до 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
Paul Michaels

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

більш читабельний з розширенням st міг написати

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

Для вашого оновленого запитання ви також можете скористатися оператором switch.

switch (myvalue)
{
   case 1:
   case 2:
   case 3: 
      // your code goes here
  break;
}

1
Це те, що я закінчив робити. Я припускаю, що консенсус полягає в тому, що в С # насправді немає жодної можливості для цього.
Paul Michaels

5
Я б насправді не прийняв цього, оскільки це НЕ відповідь на запитання оператора "in". Натомість див. Відповідь з найбільшою кількістю голосів ...
chiccodoro

6
Я б взагалі не рекомендував такий підхід! Він не є масштабованим і здатний зробити життя ваших колег-програмістів убогим!
дециклон

3
@decyclone: ​​Так, вся справа в ремонтопридатності. код, ніби наступний програміст, який замінить вас, є серійним вбивцею і знає, де ви живете.
це. __curious_geek

Я не згоден, фактичної відповіді на запитання не було (або відповідь була "ні, цього не існує в C #") - тому це здавалося мені найближчою альтернативою. Ви також повинні мати на увазі, що питання базувалося на мовній функціональності, а не на стилі.
Paul Michaels

1

В операторі немає такого, який шукає значення в колекції, натомість це метод колекції, який називається Contains.

Найбільш масштабоване рішення - використовувати a 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;

0

inКлючове слово в C # є для foreachзаяви і виразів запитів LINQ. У inC # як такої не існує функціональних можливостей, еквівалентних оператору SQL , але LINQ пропонує подібну функціональність з Contains().

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

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();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.