Подтвердить что ты не робот

Как я могу писать как "x == либо 1 или 2" на языке программирования?

Возможный дубликат:
Почему большинство языков программирования имеют только двоичные операции сравнения равенства?

У меня был простой вопрос в течение довольно долгого времени, так как я начал изучать языки программирования.

Я бы хотел написать как ", если x равен 1 или 2 = > TRUE (иначе FALSE).

Но когда я пишу его на языке программирования, скажем в C,

( x == 1 || x == 2 )

он действительно работает, но выглядит неудобно и трудно читать. Я предполагаю, что должно быть возможно упростить такую ​​операцию или операцию, поэтому, если у вас есть какие-либо идеи, скажите мне. Спасибо, Натан

4b9b3361

Ответ 1

Python позволяет тестировать членство в последовательности:

if x in (1, 2):

Ответ 2

Внутренняя версия в С#

шаг 1: создать метод расширения

public static class ObjectExtensions
{
    public static bool Either(this object value, params object[] array)
    {
        return array.Any(p => Equals(value, p));
    }
}

шаг 2: используйте метод расширения

if (x.Either(1,2,3,4,5,6)) 
{
}
else
{
}

Ответ 3

Хотя в этом потоке есть несколько довольно интересных ответов, я хотел бы указать, что они могут иметь последствия для производительности, если вы делаете такую ​​логику внутри цикла в зависимости от языка. Что касается компьютера для понимания, то if (x == 1 || x == 2) на сегодняшний день проще всего понять и оптимизировать, когда он скомпилирован в машинный код.

Ответ 4

Когда я начал программировать, мне показалось странным, что вместо чего-то вроде:

(1 < x < 10)

Мне пришлось написать:

(1 < x && x < 10)

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

Итак, я считаю, что прекрасно писать

( x == 1 || x == 2 )

Написание этого способа также имеет то преимущество, что другие программисты легко поймут, что вы написали. Использование функции для инкапсуляции может просто усложнить ситуацию, потому что другим программистам нужно будет найти эту функцию и посмотреть, что она делает.

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

Ответ 5

Это естественный, но зависимый от языка

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

Обоснование для Mess

C является системным языком программирования, и довольно близко к аппаратным средствам (смешно, хотя мы рассматривали "высокоуровневый" язык, в отличие от написания машинного кода), это не совсем expressive.

Современные языки более высокого уровня (опять же, возможно, lisp не так современно, исторически, но позволит вам сделать это хорошо) позволяют делать такие вещи, используя встроенные конструкции или поддержку библиотеки (для экземпляров, используя диапазоны, кортежи или эквиваленты в таких языках, как Python, Ruby, Groovy, ML-языки, Haskell...).

Возможные решения

Вариант 1

Один из вариантов для вас - реализовать функцию или подпрограмму, взяв массив значений и проверив их.

Вот базовый прототип, и я оставляю реализацию как упражнение для вас:

/* returns non-zero value if check is in values */
int is_in(int check, int *values, int size);

Однако, как вы быстро увидите, это очень просто и не очень гибко:

  • он работает только с целыми числами,
  • он работает только для сравнения одинаковых значений.

Вариант 2

На шаг выше по лестнице сложности (с точки зрения языков) альтернативой будет использование pre-processor макросы в C (или C++) для достижения аналогичного поведения, но остерегайтесь побочных эффектов.

Другие параметры

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

Следующим шагом было бы реализовать аналогичную вещь в C++ с помощью , чтобы сделать это на разных типах с одной реализацией.

И затем продолжайте оттуда языки более высокого уровня.


Выберите правильный язык (или научитесь отпускать!)

Как правило, языки, поддерживающие функциональное программирование, будут иметь встроенную поддержку такого рода по понятным причинам.

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

Возможно, библиотека уже реализует такую ​​вещь и что я не знаю.

Ответ 6

было много интересных альтернатив. Я удивлен, что никто не упомянул переключатель... случай - так вот идет:

switch(x) {
case 1:
case 2:
  // do your work
  break;
default:
  // the else part
}
  • это более читаемо, чем куча x == 1 || x == 2 ||...
  • более оптимальный, чем array/set/list для выполнения проверка членства

Ответ 7

Err, что с этим не так? Ну, если вы действительно используете его много и ненавидите внешний вид, сделайте что-то вроде этого в С#:

#region minimizethisandneveropen
public bool either(value,x,y){       
    return (value == x || value == y);
}
#endregion

и в тех местах, где вы его используете:

if(either(value,1,2))
   //yaddayadda 

Или что-то подобное на другом языке:).

Ответ 8

Я сомневаюсь, что я когда-нибудь это сделаю, но чтобы ответить на ваш вопрос, вот один из способов добиться этого на С#, включающий в себя небольшой общий тип вывода и некоторое злоупотребление оперативной перегрузкой. Вы можете написать код следующим образом:

if (x == Any.Of(1, 2)) {
    Console.WriteLine("In the set.");
}

Если класс Any определяется как:

public static class Any {
    public static Any2<T> Of<T>(T item1, T item2) {
        return new Any2<T>(item1, item2);
    }
    public struct Any2<T> {
        T item1;
        T item2;
        public Any2(T item1, T item2) {
            this.item1 = item1;
            this.item2 = item2;
        }
        public static bool operator ==(T item, Any2<T> set) {
            return item.Equals(set.item1) || item.Equals(set.item2);
        }
        // Defining the operator== requires these three methods to be defined as well:
        public static bool operator !=(T item, Any2<T> set) {
            return !(item == set);
        }
        public override bool Equals(object obj) { throw new NotImplementedException(); }
        public override int GetHashCode() { throw new NotImplementedException(); }
    }
}

Возможно, у вас может быть несколько перегрузок метода Any.Of для работы с 3, 4 или даже более аргументами. Другие операторы также могут быть предоставлены, а класс товарищей All может сделать что-то очень похожее, но с && вместо ||.

Глядя на разборку, справедливый бит бокса происходит из-за необходимости вызывать Equals, поэтому это заканчивается медленнее, чем очевидная конструкция (x == 1) || (x == 2). Однако, если вы измените все <T> на int и замените Equals на ==, вы получите то, что кажется встроенным, чтобы быть примерно такой же скоростью, как (x == 1) || (x == 2).

Ответ 9

В COBOL (я давно не смотрел на COBOL, поэтому у меня могут быть две или две ошибки):

IF X EQUALS 1 OR 2
...

Таким образом, синтаксис определенно возможен. Вопрос тогда сводится к "почему он не используется чаще?"

Ну, дело в том, что синтаксические выражения вроде этого немного суки. Не когда вы стоите в одиночестве, ум, но больше, когда в сложных выражениях. Синтаксис начинает становиться непрозрачным (с точки зрения реализатора компилятора) и семантикой совершенно волосатой. IIRC, многие компиляторы COBOL даже предупреждают вас, если вы используете синтаксис, подобный этому, из-за потенциальных проблем.

Ответ 10

В php вы можете использовать

$ret = in_array($x, array(1, 2));

Ответ 11

Насколько я знаю, в C. нет встроенного способа сделать это. Вы можете добавить свою собственную встроенную функцию для сканирования массива int для значений, равных x....

Так же:

inline int contains(int[] set, int n, int x)
{ 
  int i;
  for(i=0; i<n; i++)
    if(set[i] == x)
      return 1;

  return 0;
}

// To implement the check, you declare the set
int mySet[2] = {1,2};
// And evaluate like this:
contains(mySet,2,x) // returns non-zero if 'x' is contained in 'mySet'

Ответ 12

В .Net вы можете использовать Linq:

int[] wanted = new int{1, 2};

// you can use Any to return true for the first item in the list that passes
bool result = wanted.Any( i => i == x );

// or use Contains
bool result = wanted.Contains( x );

Хотя лично я думаю, что базовый || достаточно прост:

bool result = ( x == 1 || x == 2 );

Ответ 13

В T-SQL

where x in (1,2)

Ответ 14

Спасибо Игнасио! Я переводю его в Ruby:

[ 1, 2 ].include?( x )

и он также работает, но я не уверен, будет ли он выглядеть ясным и нормальным. Если вы знаете о Ruby, сообщите об этом. Также, если кто-нибудь знает, как написать это на C, пожалуйста, скажите мне. Благодарю. Натан

Ответ 15

Perl 5 с Perl6:: Junction:

use Perl6::Junction 'any';
say 'yes' if 2 == any(qw/1 2 3/);

Perl 6:

say 'yes' if 2 == 1|2|3;

Эта версия настолько читабельная и сжатая ИД использует ее вместо оператора ||.

Ответ 16

Паскаль имеет (ограниченное) понятие множеств, поэтому вы можете сделать:

if x in [1, 2] then

(не касались компилятора Pascal в течение десятилетий, поэтому синтаксис может быть отключен)

Ответ 17

В java:

 List list = Arrays.asList(new Integer[]{1,2});
 Set set = new HashSet(list);
 set.contains(1)

Ответ 18

Попробуйте только один небитовый логический оператор (не рекомендуется, не проверен):

if( (x&3) ^ x ^ ((x>>1)&1) ^ (x&1) ^ 1 == 0 )

Часть (x&3) ^ x должна быть равна 0, это гарантирует, что x находится между 0 и 3. Другие операнды будут иметь только последний бит.

Часть ((x>>1)&1) ^ (x&1) ^ 1 гарантирует, что последние и секунды для последних бит различны. Это применимо к 1 и 2, но не к 0 и 3.

Ответ 19

Вы говорите, что обозначение (x==1 || x==2) "неудобно и трудно читать". Позволю себе не согласиться. Это отличается от естественного языка, но очень понятно и легко понять. Вам просто нужно думать, как компьютер.

Кроме того, обозначения, упомянутые в этом потоке, такие как x in (1,2), семантически отличаются от того, что вы действительно спрашиваете, они спрашивают, является ли x членом set (1,2), что не является что вы просите. Вы запрашиваете if x equals to 1 or to 2, который логически (и семантически) эквивалентен if x equals to 1 or x equals to 2, который преобразуется в (x==1 || x==2).

Ответ 20

У меня есть макрос, который я использую много, что немного близко к тому, что вы хотите.

#define ISBETWEEN(Var, Low, High) ((Var) >= (Low) && (Var) <= (High))

ISBETWEEN(x, 1, 2) вернет true, если x равно 1 или 2.

Ответ 21

Ни C, С++, VB.net, С#.net, ни какой-либо другой такой язык, который я знаю, не имеет эффективного способа проверить, что что-то является одним из нескольких вариантов. Хотя (x == 1 || x == 2) часто является наиболее естественным способом кодирования такой конструкции, этот подход иногда требует создания дополнительной временной переменной:

  tempvar = somefunction(); // tempvar only needed for 'if' test:
  if (tempvar == 1 || tempvar == 2)
    ...

Конечно, оптимизатор должен иметь возможность эффективно избавиться от временной переменной (запихнуть ее в регистр за короткое время, когда она используется), но я все же считаю, что код уродлив. Кроме того, на некоторых встроенных процессорах наиболее компактный и, возможно, самый быстрый способ записи (x == const1 || x == const2 || x == const3):

  movf  _x,w             ; Load variable X into accumulator
  xorlw const1           ; XOR with const1
  btfss STATUS,ZERO      ; Skip next instruction if zero
   xorlw const1 ^ const2 ; XOR with (const1 ^ const2)
  btfss STATUS,ZERO      ; Skip next instruction if zero
   xorlw const2 ^ const3 ; XOR with (const2 ^ const3)
  btfss STATUS,ZERO      ; Skip next instruction if zero
   goto NOPE

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

Если язык имел конструкцию "если переменная является одной из нескольких констант", я бы ожидал, что компилятор будет использовать приведенный выше шаблон кода. Слишком плохо, такая конструкция не существует в общих языках.

(примечание: у Pascal есть такая конструкция, но реализация времени выполнения часто очень расточительна как для временного, так и для кода).

Ответ 22

return x === 1 || x === 2 в javascript